tnblog
首页
视频
资源
登录

Kubernetes .Net6 集群管理(一)

5803人阅读 2022/7/5 17:56 总访问:3467354 评论:0 收藏:0 手机
分类: 容器编排

Kubernetes

Kubernetes .Net6 集群管理(一)


对于Kubernetes集群的管理,.net提供了KubernetesClient库,可以对k8s集群通过简单的代码进行管理。其底层是通过找到本地的KuberConfig对集群发起的API请求。

安装


安装相关依赖库。

  1. <PackageReference Include="KubernetesClient" Version="8.0.12" />
  2. <!-- 解析库 -->
  3. <PackageReference Include="JsonPatch.Net" Version="1.1.2" />

Demo展示

初始化


通过KubernetesClientConfiguration.BuildDefaultConfig();方法可以获取到我们的本地的KUBECONFIG文件信息,它会先去环境变量中去找KUBECONFIG的地址,若没有该环境变量,便去用户名称下的.kube目录下去找该文件,如果还没有就判断自己本身是不是在集群里面,是就会通过集群中的ServiceAccount拿到相关权限,还不是就返回本地的8080的配置。(相关代码如图所示)
接着我们将初始化Kubernetes的实例.

  1. KubernetesClientConfiguration k8sConfig;
  2. Kubernetes kubeClient;
  3. public TestKubernetesClient()
  4. {
  5. // 使用凭据构建一个客户端
  6. k8sConfig = KubernetesClientConfiguration.BuildDefaultConfig();
  7. // k8s 实例
  8. kubeClient = new Kubernetes(k8sConfig);
  9. }

创建pod


可以通过定义V1Pod实例执行CreateNamespacedPodAsync方法进行创建相关Pod。
这里我们在default命名空间下创建一个镜像为burlyluo/nettoolbox名为busybox的pod,并为它添加run=busybox标签。

  1. [DataTestMethod]
  2. [DataRow("default", "busybox", "burlyluo/nettoolbox", "run=busybox")]
  3. public async Task TestCreatePod(string mynamespace, string Podname,string image,string labels)
  4. {
  5. #region 创建一个pod
  6. var pod = new V1Pod()
  7. {
  8. ApiVersion = "v1",
  9. Kind = "Pod",
  10. Spec = new V1PodSpec() { Containers = new List<V1Container>() },
  11. Metadata = new V1ObjectMeta() { Labels = new Dictionary<string, string>() }
  12. };
  13. // 取名
  14. pod.Metadata.Name = Podname;
  15. // 标记标签
  16. if (!string.IsNullOrEmpty(labels))
  17. {
  18. var labelsDictionary = labels.Split(',').Select(x => x.Split('=')).ToDictionary(x => x[0], y => y[1]);
  19. foreach (var item in labelsDictionary)
  20. {
  21. pod.Metadata.Labels[item.Key] = item.Value;
  22. }
  23. }
  24. // 创建一个容器
  25. var container = new V1Container(Podname)
  26. {
  27. // Command
  28. // Args
  29. // Env
  30. // Ports
  31. // 定义镜像
  32. Image = image,
  33. // 拉取镜像策略
  34. ImagePullPolicy = "IfNotPresent"
  35. };
  36. pod.Spec.Containers.Add(container);
  37. #endregion
  38. // 创建pod
  39. await kubeClient.CreateNamespacedPodAsync(pod, mynamespace).ConfigureAwait(false);
  40. }


执行该测试方法后,我们通过命令查看已经创建成功了。

  1. kubectl get pod

获取Pod信息


我们这里我们通过ListNamespacedPodAsync方法找到label相匹配的所有pod信息,输出了Pod的名称以及它的IP。

  1. [DataTestMethod]
  2. [DataRow("default", "run=busybox")]
  3. public async Task TestGetPod(string mynamespace,string labels)
  4. {
  5. // 获取现有的Pod
  6. var pods = await kubeClient.ListNamespacedPodAsync(mynamespace,
  7. null, null, null, labels);
  8. foreach (var pod in pods.Items)
  9. {
  10. Debug.WriteLine($"现有的 Lable[{labels}] Pod: {pod.Metadata.Name} Pod IP: {pod.Status.PodIP}");
  11. }
  12. }


我们还可以通过服务的方式去找到相关的Pod。方法为找到相关服务,获取服务所选取的标签再拿这些标签去找到相关Pod。

  1. /// <summary>
  2. /// 通过服务获取pod
  3. /// </summary>
  4. /// <param name="mynamespace"></param>
  5. /// <param name="labels"></param>
  6. /// <returns></returns>
  7. [DataTestMethod]
  8. [DataRow("swprinter", "swpapi")]
  9. public async Task TestGetServicePod(string mynamespace, string servicename)
  10. {
  11. var myservice = await kubeClient.ReadNamespacedServiceAsync(servicename, mynamespace);
  12. var labels = myservice.Spec.Selector.Select(x => $"{x.Key}={x.Value}")
  13. .ToArray()
  14. ;
  15. var labelString = string.Join(',', labels);
  16. // 获取现有的Pod
  17. var pods = await kubeClient.ListNamespacedPodAsync(mynamespace,
  18. null, null, null, labelString);
  19. foreach (var pod in pods.Items)
  20. {
  21. Debug.WriteLine($"现有的 Lable[{labelString}] Pod: {pod.Metadata.Name} Pod IP: {pod.Status.PodIP}");
  22. }
  23. }

添加标签


我们为默认名称空间下的带有run=busybox标签的Pod,添加新的的标签name=busybox,注意在修改完成后通过PatchNamespacedPodAsync方法进行保存修改。

  1. [DataTestMethod]
  2. [DataRow("default", "run=busybox", "name=busybox")]
  3. public async Task TestSetPod(string mynamespace, string searchlabels, string nowlabels)
  4. {
  5. // 获取现有的Pod
  6. var pods = await kubeClient.ListNamespacedPodAsync(mynamespace,
  7. null, null, null, searchlabels);
  8. // label分割
  9. var _nowlabels = nowlabels.Split(',')
  10. .Select(x => x.Split('='))
  11. .ToDictionary(x => x[0], y => y[1]);
  12. // 获取共有部分
  13. var all_labels = pods.Items.SelectMany(x => x.Metadata.Labels.Keys).Union(_nowlabels.Keys);
  14. // 获取差的部分
  15. foreach (V1Pod pod in pods.Items)
  16. {
  17. // 修改前
  18. Debug.WriteLine($"修改前 Label--[{Newtonsoft.Json.JsonConvert.SerializeObject(pod.Metadata.Labels)}] Pod: {pod.Metadata.Name} Pod IP: {pod.Status.PodIP}");
  19. var old = JsonSerializer.SerializeToDocument(pod);
  20. foreach (var label in _nowlabels)
  21. {
  22. var boolvalue = pod.Metadata.Labels.TryAdd(label.Key, label.Value);
  23. }
  24. var expected = JsonSerializer.SerializeToDocument(pod);
  25. var patch = old.CreatePatch(expected);
  26. var patchn = new V1Patch(patch, V1Patch.PatchType.JsonPatch);
  27. await kubeClient.PatchNamespacedPodAsync(patchn, pod.Name(), mynamespace);
  28. // 修改后
  29. Debug.WriteLine($"修改后 Label--[{Newtonsoft.Json.JsonConvert.SerializeObject(pod.Metadata.Labels)}] Pod: {pod.Metadata.Name} Pod IP: {pod.Status.PodIP}");
  30. }
  31. }


删除就是Remove什么的就不讲了。。。

监控事件情况


我们通过下面的代码可以监控Pod的事件,其实这里就是一个Watch方法内部带了委托,然后上了个锁防止程序退出。我们先执行,然后打开窗口执行删除pod的命令。

  1. /// <summary>
  2. /// 监控命名空间下pod的情况与事件
  3. /// 监听新创建的Pod
  4. /// </summary>
  5. /// <param name="mynamespace"></param>
  6. /// <returns></returns>
  7. [DataTestMethod]
  8. [DataRow("default")]
  9. public async Task TestWatchPod(string mynamespace)
  10. {
  11. // 获取现有的Pod消息任务
  12. using var listTask = await kubeClient.CoreV1.ListNamespacedPodWithHttpMessagesAsync(mynamespace, watch: true).ConfigureAwait(false);
  13. var connectionClosed = new AsyncManualResetEvent();
  14. // 监听新的pod创建情况
  15. listTask.Watch<V1Pod, V1PodList>(
  16. (type, item) =>
  17. {
  18. // 过滤掉Add类型并不新创建的pod情况
  19. if (type == WatchEventType.Added && !string.IsNullOrEmpty(item?.Metadata.Name))
  20. {
  21. return;
  22. }
  23. Debug.WriteLine($"监视到事件 '{type}',相关 Pod: {item!.Metadata.Name}");
  24. },
  25. error =>
  26. {
  27. Debug.WriteLine($"监视到错误 '{error.GetType().FullName}'");
  28. },
  29. connectionClosed.Set);
  30. Debug.WriteLine("等待新的 Pod 事件...");
  31. await connectionClosed.WaitAsync();
  32. }
  1. kubectl delete pod/busybox

在集群中监控


首先我们创建一个K8sWatch的控制台项目,安装相关依赖包,然后将我们刚刚的代码放入到Program.cs中。

  1. using k8s;
  2. using k8s.Models;
  3. using Nito.AsyncEx;
  4. // 使用凭据构建一个客户端
  5. var k8sConfig = KubernetesClientConfiguration.BuildDefaultConfig();
  6. // k8s 实例
  7. var kubeClient = new Kubernetes(k8sConfig);
  8. // 获取现有的Pod消息任务
  9. using var listTask = await kubeClient.CoreV1.ListNamespacedPodWithHttpMessagesAsync("default", watch: true).ConfigureAwait(false);
  10. var connectionClosed = new AsyncManualResetEvent();
  11. // 监听新的pod创建情况
  12. listTask.Watch<V1Pod, V1PodList>(
  13. (type, item) =>
  14. {
  15. // 过滤掉Add类型并不新创建的pod情况
  16. if (type == WatchEventType.Added && !string.IsNullOrEmpty(item?.Metadata.Name))
  17. {
  18. return;
  19. }
  20. Console.WriteLine($"监视到事件 '{type}',相关 Pod: {item!.Metadata.Name}");
  21. },
  22. error =>
  23. {
  24. Console.WriteLine($"监视到错误 '{error.GetType().FullName}'");
  25. },
  26. connectionClosed.Set);
  27. Console.WriteLine("等待新的 Pod 事件...");
  28. await connectionClosed.WaitAsync();


然后通过以下命令发布Linux的可执行程序。

  1. dotnet publish -r linux-x64 -p:PublishSingleFile=true


然后我们在rbac-good-permission.yaml文件下定义相关的ServiceAccount以及Role使我们需要运行的程序具有一定的权限,这里权限我们给得不多,只给了对pod的getlistwatch三个权限。

  1. kind: ServiceAccount
  2. apiVersion: v1
  3. metadata:
  4. name: pod-operator
  5. namespace: default
  6. ---
  7. apiVersion: rbac.authorization.k8s.io/v1
  8. kind: Role
  9. metadata:
  10. name: pod-operator-role
  11. namespace: default
  12. rules:
  13. - apiGroups: [ "" ]
  14. resources: [ "pods", "pods/exec" ]
  15. verbs: [ "get", "list", "watch" ]
  16. ---
  17. apiVersion: rbac.authorization.k8s.io/v1
  18. kind: RoleBinding
  19. metadata:
  20. name: pod-operator-role
  21. namespace: default
  22. roleRef:
  23. apiGroup: rbac.authorization.k8s.io
  24. kind: Role
  25. name: pod-operator-role
  26. subjects:
  27. - kind: ServiceAccount
  28. name: pod-operator
  29. namespace: default
  1. kubectl create -f .\rbac-good-permission.yaml


接着我们编写一个测试的Pod文件(test-pod.yaml),并执行。

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. labels:
  5. app: test
  6. name: test-pod
  7. spec:
  8. serviceAccountName: pod-operator
  9. containers:
  10. - image: mcr.microsoft.com/dotnet/runtime:6.0
  11. imagePullPolicy: IfNotPresent
  12. name: tester
  13. args:
  14. - infinity
  15. command:
  16. - sleep
  1. kubectl create -f .\test-pod.yaml


然后将我们程序放入到该pod中,并执行。随后打开另一个窗口添加新的pod进行测试监控,发现没有问题。

  1. # 到发布的路径下
  2. cd D:\Learning\k8sPlugs\K8sWatch\bin\Debug\net6.0\linux-x64\publish\
  3. # -c 表示指定的容器
  4. kubectl cp K8sWatch default/test-pod:/home/ -c tester
  5. # 进入容器
  6. kubectl exec -it test-pod -c tester -- /bin/bash
  7. cd /home
  8. chmod +x ./K8sWatch
  9. ./K8sWatch
  1. kubectl run busybox --image=burlyluo/nettoolbox


然后我们退出,创建一个rbac-no-permission.yaml并更新pod-operator-role角色的权限使它没有任何访问权限。

  1. ---
  2. apiVersion: rbac.authorization.k8s.io/v1
  3. kind: Role
  4. metadata:
  5. name: pod-operator-role
  6. namespace: default
  7. rules:
  8. - apiGroups: [ "" ]
  9. resources: [ "pods" ]
  10. verbs: [ "" ]
  1. kubectl delete role/pod-operator-role
  2. kubectl apply -f rbac-no-permission.yaml


再次运行它将报错。


欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

评价

C ?、?? 问号和2个问号的用法类型?、对象?

C# ?C# ???:单问号1.定义数据类型可为空。可用于对int,double,bool等无法直接赋值为null的数据类型进行null的赋值如这...

Python实例 1-日志抓取处理 补错附日志小技巧

有时候数据出了问题,可以从日志中恢复数据(如果你没记日志..没备份..→_→..)一、日志展示介绍个平常自己用的小方法,如...

C 数组拆分泛型

主要用到了泛型。泛型是c#2.0的一个新增加的特性,它为使用c#语言编写面向对象程序增加了极大的效力和灵活性。不会强行对值...

MySQL 视图的增删改 查

要显示视图的定义,需要在SHOWCREATEVIEW子句之后指定视图的名称, 我们先来创建几张表,完事后在进行演示:--用户信息表...

使用NPOI导出excel包括图片

Excl模板导出相信我们都会,那么模板上要导出图片呢?嗯~还是来个例子:准备工作:首先要引用NPOI包:然后获取数据集(我这...

ajaxSubmit异步上传图片嘘,外面都是假的

引用代码&lt;scriptsrc=&quot;/Scripts/jquery.form.js&quot;&gt;&lt;/script&gt;js就在旁边img链接中,只不过大小为0x0,...

.net MVC 使用百度编辑器详细教程:1配置编辑器

一、什么是百度编辑器百度编辑器UEditor是由百度web前端研发部开发一款应用于网站的编辑器,具有轻量,可定制,注重用户体...

使用jquery操作元素的css样式获取、修改等等

使用jquery操作元素的css样式(获取、修改等等) //1、获取和设置样式 $(&quot;#tow&quot;).attr(&quot;class&quot;)...

.net辗转java系列视野

.net辗转java系列(一)视野.net系java系其它语言C#Java框架.net Framework Standardjava se.net corejava eejave meJava S...

.net MVC json对象或者json对象数组的序列化和反序列化

1、用JSON.stringify()将对象stuarr或者json数组stuarr序列化成字符串,然后提交给后台。$.post(&quot;/home/DoUpdate&quot...

.net MVC json对象或者json对象数组的序列化和反序列化

1、用JSON.stringify()将对象stuarr或者json数组stuarr序列化成字符串,然后提交给后台。$.post(&quot;/home/DoUpdate&quot...

mui框架-移动端跳转以及传值的简单方法修改解决方法

纠结了两天的MUI跳转的问题,终于解决了 ,现在分享给大家,希望大家有什么坑的解决也给我分享分享 哈哈,废话不多说,上代...

MVC全局异常处理错误日记

1、在Filter文件夹中创建一个IsExceptionFilter类(类名随意取)2、使用3、在访问的页面控制器中添加几个错误4、在IsExcept...

MVC全局异常处理错误日记

1、在Filter文件夹中创建一个IsExceptionFilter类(类名随意取)2、使用3、在访问的页面控制器中添加几个错误4、在IsExcept...

Hbuilder打包APP的教程会操作的略过

首先项目必须是APP端的,可能讲解有点啰嗦,讲解准备的工具:HBuilderX(其他版本也可以,这里用X版本来讲解)、待测试手机...
这一世以无限游戏为使命!
排名
2
文章
634
粉丝
44
评论
93
docker中Sware集群与service
尘叶心繁 : 想学呀!我教你呀
一个bug让程序员走上法庭 索赔金额达400亿日元
叼着奶瓶逛酒吧 : 所以说做程序员也要懂点法律知识
.net core 塑形资源
剑轩 : 收藏收藏
映射AutoMapper
剑轩 : 好是好,这个对效率影响大不大哇,效率高不高
ASP.NET Core 服务注册生命周期
剑轩 : http://www.tnblog.net/aojiancc2/article/details/167
ICP备案 :渝ICP备18016597号-1
网站信息:2018-2025TNBLOG.NET
技术交流:群号656732739
联系我们:contact@tnblog.net
公网安备:50010702506256
欢迎加群交流技术