当前位置: 首页 > news >正文

Kubernetes WebHook 入门 -- 入门案例: apiserver 接入 github

在这里插入图片描述

博客原文

文章目录

    • k8s 集群配置
    • 介绍
    • Admission Webhook
    • WebHook 入门实践: github 认证接入
      • web 服务器
      • Dockerfile 镜像制作
        • amd64
        • x86_64
        • 构造镜像
        • 检验镜像
      • Makefile
      • webhook 接入 apiserver
        • webhook.yaml
        • apiserver 挂载 webconfig
        • 在 github 中创建认证 token
        • 将 token 添加到 kubeconfig
      • 验证
        • 授权验证
    • deploy spec
    • 参考

k8s 集群配置

IPHost配置
11.0.1.150master1 (keepalived+haproxy)2C 4G 30G
11.0.1.151master2 (keepalived+haproxy)2C 4G 30G
11.0.1.152node12C 4G 30G

vip 地址: https://11.0.1.100:16443

介绍

Webhook就是一种HTTP回调,用于在某种情况下执行某些动作,Webhook不是K8S独有的,很多场景下都可以进行Webhook,比如在提交完代码后调用一个Webhook自动构建docker镜像

K8S中提供了自定义资源类型自定义控制器来扩展功能,还提供了动态准入控制,其实就是通过Webhook来实现准入控制,分为两种:验证性质的准入 Webhook (Validating Admission Webhook) 和 修改性质的准入 Webhook (Mutating Admission Webhook)

Admission Webhook有哪些使用场景?如下

  • 在资源持久化到ETCD之前进行修改(Mutating Webhook),比如增加init Container或者sidecar Container
  • 在资源持久化到ETCD之前进行校验(Validating Webhook),不满足条件的资源直接拒绝并给出相应信息

现在非常火热的的 Service Mesh 应用istio就是通过 mutating webhooks 来自动将Envoy这个 sidecar 容器注入到 Pod 中去的:
https://istio.io/docs/setup/kubernetes/sidecar-injection/。

更多详情介绍可参考:
https://kubernetes.io/zh/docs/reference/access-authn-authz/extensible-admission-controllers/

Admission Webhook

上面提到K8S的动态准入控制是通过Webhook来实现的,那么它到底是在哪个环节执行的?请看下图

在这里插入图片描述

综上, k8s webhook 可分为两类:

  1. Mutating Webhook: 这类 webhook 可以更改请求对象
  2. Validating Webhook: 这类 webhook 不能去更改请求对象, 就算更改也会被忽略, 用于写入 etcd 前的验证逻辑

WebHook 入门实践: github 认证接入

源码地址: https://github.com/Ai-feier/k8s-webhook/tree/main/auth-github

写一个用于认证校验的 mutating webhook

请求流程:

  1. 拦截 apiserver 请求
  2. 将请求(TokenReview)中的 token 发送给 github 用于验证
  3. 将 github 返回的用户信息填入 TokenReview

web 服务器

package mainimport ("context""encoding/json""github.com/google/go-github/github""golang.org/x/oauth2"authentication "k8s.io/api/authentication/v1beta1""log""net/http"
)func main() {http.HandleFunc("/authenticate", func(writer http.ResponseWriter, request *http.Request) {// 获取请求中的 TokonReviewdecoder := json.NewDecoder(request.Body)var tokenReview authentication.TokenReviewif err := decoder.Decode(&tokenReview); err != nil {log.Println("decode error: ", err)// 响应返回错误writer.WriteHeader(http.StatusBadRequest)_ = json.NewEncoder(writer).Encode(map[string]interface{}{"apiVersion": "authentication.k8s.io/v1beta1","kind":       "TokenReview","status": authentication.TokenReviewStatus{Authenticated: false,},})return}log.Println("receive request")// 检查用户// 创建 oauth2 对象, 发送给 githuboauthToken := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: tokenReview.Spec.Token, // tokenReview 的 token})oauthClient := oauth2.NewClient(context.Background(), oauthToken)client := github.NewClient(oauthClient)user, _, err := client.Users.Get(context.Background(), "")if err != nil {log.Println("github auth error: ", err)writer.WriteHeader(http.StatusUnauthorized)_ = json.NewEncoder(writer).Encode(map[string]any{"apiVersion": "authentication.k8s.io/v1beta1","kind":       "TokenReview","status": authentication.TokenReviewStatus{Authenticated: false, // 返回认证失败},})return}// 认证成功log.Println("github login success, as: ", *user.Login)status := authentication.TokenReviewStatus{Authenticated: true,User: authentication.UserInfo{Username: *user.Login,UID: *user.Login,},}json.NewEncoder(writer).Encode(map[string]any{"apiVersion": "authentication.k8s.io/v1beta1","kind":       "TokenReview","status": status,})})log.Println(http.ListenAndServe(":3000", nil))
}

Dockerfile 镜像制作

本项目是使用 go 作为 web 服务器, go 提供一种非常好用的编译特性 – 交叉编译

在 dockerfile 中我们选择的 busybox 作为基础镜像, 但默认 busybox 架构为 x86_64(uname -m查看), 所以可以使用 amd64/busybox 或交叉编译 go 代码

当出现这类问题 exec /usr/bin/sh: exec format error 多半是架构问题

推荐: Golang交叉编译详解 – CSDN

amd64
FROM golang:1.20 as builderWORKDIR /appCOPY . .# go 交叉编译: amd64
RUN go env -w  GOPROXY=https://goproxy.cn,direct && go mod tidy && \CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main main.go RUN chmod +x /app/mainFROM amd64/busyboxCOPY --from=builder /app/main .EXPOSE 3000/tcpCMD ["/main"]
x86_64
FROM golang:1.20 as builderWORKDIR /appCOPY . .# go 交叉编译: x86
RUN go env -w  GOPROXY=https://goproxy.cn,direct && go mod tidy && \CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -o main main.go RUN chmod +x /app/mainFROM busyboxCOPY --from=builder /app/main .EXPOSE 3000/tcpCMD ["/main"]
构造镜像
$ docker build -t aifeierwithinmkt/auth-github-webhook:amd64 -f Dockerfile_amd64 .$ docker build -t aifeierwithinmkt/auth-github-webhook:x86 -f Dockerfile_x86 .$ docker tag aifeierwithinmkt/auth-github-webhook:amd64 aifeierwithinmkt/auth-github-webhook
检验镜像
$ docker run --rm -p 3000:3000 -d aifeierwithinmkt/auth-github-webhook:amd64
$ docker run --rm -p 3001:3000 -d aifeierwithinmkt/auth-github-webhook:x86$ curl 127.0.0.1:3000/authenticate
{"apiVersion":"authentication.k8s.io/v1beta1","kind":"TokenReview","status":{"user":{}}}
$ curl 127.0.0.1:3001/authenticate
{"apiVersion":"authentication.k8s.io/v1beta1","kind":"TokenReview","status":{"user":{}}}

镜像服务正常

Makefile

build_amd64:mkdir -p bin/amd64CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/amd64/main .build_x86:mkdir -p bin/x86CGO_ENABLED=0 GOOS=linux GOARCH=386 go build -o bin/x86/main .	

webhook 接入 apiserver

webhook.yaml
apiVersion: v1
clusters:
- cluster:server: http://192.168.1.7:3000/authenticatename: github-authn
contexts:
- context:cluster: github-authnuser: authn-apiservername: webhook
current-context: webhook
kind: Config
preferences: {}
users:
- name: authn-apiserveruser:client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURJVENDQWdtZ0F3SUJBZ0lJRlYrSjRRNm1heUF3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TXpFeU16QXdPVE16TVRkYUZ3MHlOREV5TWprd09UTTRNVGxhTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQTQ2NTQzOWp6cVpqcldXd3EKMkloeWtQcjREb3MySnNTM0JrUlhJTzY2UnhhbmxqVGszWlBka21oaUFvRldHTHI5VitwTUdwTytVYzhmbHhDKwoyZVc3QmVwelhzVjd2Y1RRZ25RMVlnVGh2bldRdkxVVFJuUXhoUHhYS2RGNzBEL2RISkxjMGxyVHhjZ2JNUUVTCmdPZWZZQm03dWdBdEJ0RDg3MitrdWVuV3RIc201a09nd0l0N3EzbjVvQ1huZWd4VHBFTHFtcmhtQTYrUXcrNXkKbEg1bG5LdzlFdUJmYmVqY0ZOaEd2UVNFSmFNZ2s0Z2h4bUNQWHJUcFZ0bmRkMHJQMGc4dzkvQ0NKU1owdDV6TApHMk5idFlqQzRRK2tyQXZoSllIUGRzVkRtWTFpMkZsSmsyZGgyU0RzbzJLMGNldmMvRGpUaTdhbGNpTlQwU05ICjFoVXpsd0lEQVFBQm8xWXdWREFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RBWURWUjBUQVFIL0JBSXdBREFmQmdOVkhTTUVHREFXZ0JRU1oxaVlWKzlQNTRiNHB3UU9QVkI0TklXYgp3REFOQmdrcWhraUc5dzBCQVFzRkFBT0NBUUVBV3pmWXJMWUd5ZGJoM0hpRmxVMWhuR2ZYeGxDMGk3VDBNMmZ1CnZMUkJBM1lYelRMQmNJeFhjT3J2R2Z1OGp3ZE1qY1VmZ2tuQ0JOL2VrN2lqSDF6ZmxmRkVwK0JiWHE2WFpUQWQKTkh1aGdKVG5SRUV4OURHNldtLy9wNnpZOExEVU1ZekZwZGYyYkt2ZWdkQ0NaT3R5OTJ2eFZmbUJ5THJnUHYwRQpGSEZhR1ZCQ083Z012VnFCN05rMGxVN3Axdjg3YzVBTmJxUHI2YjYyZmMzbE9XcGQ2bUN0bDFjdms1QWROczJlCnBRVlFBRnhGR1o3WGFDaU9waFM3L2M1Vm1MUk9lWERHZ1BjUnNjdEtZL0VybXNqQ2JrYnpobnUydk85dnJPRVQKZEh0QlBYRlBYV29PWTVsZWlQa29WRUs4S1FFMmhPWVBpZDhIVHNhZzl1ZGc2Zkwvenc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBNDY1NDM5anpxWmpyV1d3cTJJaHlrUHI0RG9zMkpzUzNCa1JYSU82NlJ4YW5salRrCjNaUGRrbWhpQW9GV0dMcjlWK3BNR3BPK1VjOGZseEMrMmVXN0JlcHpYc1Y3dmNUUWduUTFZZ1Rodm5XUXZMVVQKUm5ReGhQeFhLZEY3MEQvZEhKTGMwbHJUeGNnYk1RRVNnT2VmWUJtN3VnQXRCdEQ4NzIra3Vlbld0SHNtNWtPZwp3SXQ3cTNuNW9DWG5lZ3hUcEVMcW1yaG1BNitRdys1eWxINWxuS3c5RXVCZmJlamNGTmhHdlFTRUphTWdrNGdoCnhtQ1BYclRwVnRuZGQwclAwZzh3OS9DQ0pTWjB0NXpMRzJOYnRZakM0UStrckF2aEpZSFBkc1ZEbVkxaTJGbEoKazJkaDJTRHNvMkswY2V2Yy9EalRpN2FsY2lOVDBTTkgxaFV6bHdJREFRQUJBb0lCQUJIaWRxUSt5b1ViK2dEQQpPbTFmNm4vdzl1Tk5sQ2RmZEhFTmxUcUZCaVRuWnFxcDVRQnl5UWpqSWkvSU1SY29PUlphMVRlUk8zWDVxeVdXCnJ5YzJvSVpLY0YyVmJhN3VjdUtNZGxVSXhTTE00VjJ4YTU0eEttS2ozOFR0SzZpa0c1NU8rd0diR04rRVpINW8KOHljbENxUGw0WlV1eGxxdXQrK20rVzJSTE1ob2JoOG1mb1RDNGExczJlMEdpM3lkdE16SjNXZnczcUUvUlRGbQoyYm0rMHd6bFlUaXB2cmo4OEJ0aHBQUDlrTmJyVEs4WFNROXUzMnNjS3VWVllpcUJpeStMVUhMek5GY09ZbkpPCjBtdUFsTTFhTmh2WXJQMnI4QThkLzZtays5eDN6THVlM1NVYm1BdTJFUFdMKzZneUxiRHIrV1RJeHYxRVNQS0EKZW5TcWRRRUNnWUVBNVZZMGloY3I2Y0pGbkZZUnBJTjRSUjVrejBhdE12RUZmQWhIbERoUVQrUmpCTXRkVHlFSApNQVFqdXlZaDhReEh0TmxEQzBJTFJTdWpPSWdhZHFsMlBmbzNwR1RmM0xlbExkbGx4amRsVTZJc0lLYVVDdWw5CndPcTBmbkVTbUVUdGdxZS9nazFMS01ZMXUyOXg2S2FkZ25RSlBybFlQT21idW1SY3pydHc3N2NDZ1lFQS9pY0EKcnhDODcvc3VDQS9HUXpRdWlvVWphd0NXSEgyVnE2eUlSNDRVWXJaNWMwRXl1OU5jOFhoQVhTbGJxNzF6NkNDMgpFQVE4cm8weWFWTFB2TDFWeDB2aDVKUjVnaHVkMkcvMFdPbzFVR0l1SFhPaGpSeWR3UDlzZ2NZRGpUaitHYlJNCjlkSWJrWi9YcWx3Uzh2aVJHQ1BaN3hjVm5pTlJ5RzJ5N3BxeUd5RUNnWUIxNDdlRVdONzQvaVc4ZEw0Qy9KWWgKcWJzV2xmVkluMzg3UUNKVGZoTkN6bHRjUnBJRHNDMjZzQllTQ1VzZlZ6bXhMSkg3UW9yNmxyRUR5V3NaSG9tcQoyR29yOXJMaENnSStMR2ZWMmZvYllOMGdONkVZYnVoMjkrK3FvOE4wUk5KMi9IWkVyQ2o3bjlCVk5yZXVhWi9FClJKUFFDNFRoWXhEcll0WVdhMkpseHdLQmdRRFh3SjU0LzNtVk5DTkFucnVOZzNmYkNla21SZ29veDRmT2hCbncKdkxHYmx4S0ZBQjBraStyRDVuU2xZWjI3cm9uOXpmOGdtNmd6K2hPSWk4OWtoMHFSZEY2Z29GYUNXQlZvanFuYwo3WDR5N2hYOTFKS1phMmlVVllGMHJYZUlaSkI1bTdFVm9iYmJxZGo0ZTA5dXlncktkbXprNWpEbzNVenBIQThoCk5WdnJZUUtCZ1FDNDRreXNsRlBUVkNlbkp5SDFHLy82VmQ0aXRFaFlYQVllYWJUdU15eVlkZFlxcnJYTTFUS1QKL24wRHQrQXFIa0dmU2pvUExCa3NITkNDZWZnZSt0dDRxVmFPNjJyWkhRRTQ0TXVueHhxRXBNdmxFeUNEVUM4cApTaUF6bW9XaDR4R2tUdkpLUlBLWGlPNEdjbk5wZVNuUVY5RjJSY01ocllCUVZjTzJLb2N1Umc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=

该配置与 kubeconfig 配置相同, 直接在 kubeconfig 的基础上修改就行, 重要的是 cluster 的 server (即提供服务的地址

apiserver 挂载 webconfig
# 修改 apiserver 配置参数, 增加:
- --authentication-token-webhook-config-file=/etc/config/webhook.yaml# 相应增加挂载卷volumes:- hostPath:path: /etc/configtype: DirectoryOrCreatename: auth-webhookvolumeMounts:- mountPath: /etc/configname: auth-webhookreadOnly: true
  1. 修改 manifest 后 apiserver 理论上会自动重启, 如果没有则 systemctl restart kubelet
  2. 本文实验主题为认证 webhook 可直接使用 --authentication-token-webhook-config-file, 如需自定义 mutatingwebhook 请参考: mutatingwebhook
在 github 中创建认证 token

setting -> Developer Settings -> Personal access tokens (classic)

将 token 添加到 kubeconfig
# 在 kubeconfig 下增加一个 user
- name: githubuseruser:token: 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

验证

$ k get po --user githubuser
Error from server (Forbidden): pods is forbidden: User "Ai-feier" cannot list resource "pods" in API group "" in the namespace "default"
授权验证
$ k create clusterrolebinding testview --clusterrole view --user Ai-feier
$ k get po --user githubuser
NAME                         READY   STATUS    RESTARTS      AGE
nginx-kusc00401              0/1     Pending   0             4d23h
testnginx-5cdb847cd9-7nm4k   1/1     Running   1 (29h ago)   43h
testnginx-5cdb847cd9-llmxf   1/1     Running   1 (29h ago)   43h
testnginx-5cdb847cd9-qfsdn   1/1     Running   1 (29h ago)   43h
web-server                   0/1     Pending   0             4d22h

deploy spec

apiVersion: apps/v1
kind: Deployment
metadata:labels:app: auth-webhookname: auth-webhooknamespace: default
spec:replicas: 3selector:matchLabels:app: auth-webhookstrategy: {}template:metadata:labels:app: auth-webhookspec:containers:- image: aifeierwithinmkt/auth-github-webhookname: auth-github-webhookresources: {}ports:- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:name: auth-svcnamespace: default
spec:selector:app: auth-webhookports:- name: authprotocol: TCPport: 80targetPort: 3000

参考

  1. https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/extensible-admission-controllers/

相关文章:

Kubernetes WebHook 入门 -- 入门案例: apiserver 接入 github

博客原文 文章目录 k8s 集群配置介绍Admission WebhookWebHook 入门实践: github 认证接入web 服务器Dockerfile 镜像制作amd64x86_64构造镜像检验镜像 Makefilewebhook 接入 apiserverwebhook.yamlapiserver 挂载 webconfig在 github 中创建认证 token将 token 添加到 kubecon…...

办公软件巨头CCED、WPS面临新考验,新款办公软件异军突起

办公软件巨头CCED、WPS的成长经历 众所周知,CCED和WPS在中国办公软件领域树立了两大知名品牌的地位。然而,它们的成功并非一朝一夕的成就,而是历经了长时间的发展与积淀。 在上世纪80年代末至90年代初,CCED作为中国大陆早期的一款…...

unity角色触摸转向

1、挂载脚本到角色的父物体A上 2 、以屏幕左边的触摸为移动,右边为转向操作 3、加载角色时,将角色的父物体设置为A,须将角色的位置和角度置0 using System; using System.Collections; using System.Collections.Generic; using UnityEngin…...

世界顶级汽车品牌源代码遭泄露 详解源代码凭据安全解决方案

源代码凭据安全,您别忽视 !!! 一、事件回顾 2024年1月29日,RedHunt 实验室的研究员Lohit爆料:某世界顶级的豪华汽车品牌源代码面临泄露风险!人为错误致GitHub令牌事故引发重大安全担忧。 RedHunt Labs在一次互联网扫描时&#x…...

Mysql-备份与恢复

目录 一、备份表 1.无需备份表结构 2.备份表结构 3.mysqldump方式备份表 二、备份库 一、备份表 1.无需备份表结构 CREATE TABLE a_bak as select * from a;#备份表(不包含表结构)TRUNCATE TABLE a;#清空表 INSERT INTO a SELECT * FROM a_bak;#插…...

基于STM32的UART/USART数据传输的错误检测和纠错机制研究

在STM32的UART/USART数据传输过程中,为了确保数据的可靠性,通常需要使用错误检测和纠错机制。常见的错误检测和纠错技术包括奇偶校验、循环冗余校验(CRC)、硬件流控制和重发机制等。本文将重点介绍这些技术在STM32上的应用&#x…...

「优选算法刷题」:计算布尔二叉树的值

一、题目 给你一棵 完整二叉树 的根,这棵树有以下特征: 叶子节点 要么值为 0 要么值为 1 ,其中 0 表示 False ,1 表示 True 。非叶子节点 要么值为 2 要么值为 3 ,其中 2 表示逻辑或 OR ,3 表示逻辑与 AND…...

A系统数据表同步到B系统数据表

一、 事务操作 (小量数据) 事务操作通常用于确保数据的一致性和完整性。以下是一些常见的应用场景: 银行转账:当从一个账户向另一个账户转账时,需要确保两个操作(从一个账户扣款和向另一个账户存款&#x…...

Qt实现类似ToDesk顶层窗口 不规则按钮

先看效果: 在进行多进程开发时,可能会遇到需要进行全局弹窗的需求。 因为平时会使用ToDesk进行远程桌面控制,在电脑被控时,ToDesk会在右下角进行一个顶层窗口的提示,效果如下: 其实要实现顶层窗口&#xf…...

发布4-运行JRT程序

到了本章节,你需要准备好JDK17的环境和idea环境。并且安装好选择的数据库软件。这章将正式开始JRT的程序开发。 首先获取程序,我会给下载地址 下载后解压会得到下图目录的文件结构,DBFile放IRIS和PG的数据库文件,JRTClient放打包…...

利用VPN设备漏洞入侵!新型勒索软件CACTUS攻击手法分析

近期,亚信安全应急响应中心截获了利用VPN设备已知漏洞传播的新型勒索软件CACTUS,该勒索于2023年3月首次被发现,一直保持着活跃状态。CACTUS勒索软件通过Fortinet VPN的已知漏洞进行入侵(黑客首先获取到VPN账号,再通过V…...

第7章 SpringBoot安全管理

学习目标 了解SpringSecurity安全管理的功能 掌握SpringSecurity的安全配置 掌握SpringSecurity自定义用户认证的实现方法 掌握SpringSecurity自定义用户授权管理的实现方法 掌握如何使用SpringSecurity实现页面控制 实际开发中,一些应用通常要考虑到安全性问题。例如,对于一…...

【QT+QGIS跨平台编译】之二十二:【FontConfig+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

文章目录 一、FontConfig介绍二、文件下载三、文件分析四、pro文件五、编译实践 一、FontConfig介绍 FontConfig 是一个用于配置和定制字体的库,广泛应用于基于X Window系统的操作系统中,尤其是在Linux和Unix-like系统中。它为应用程序提供了一种统一的…...

echarts中绘制3D三维地球

简介 echarts中的三维地球,需要用到世界地图json数据,我把json文件放到我的资源中,有需要的自行下载。 安装插件 // 安装echats npm install echarts --save npm install echarts-gl --save 项目中引用 1,引入安装的echarts…...

go grpc高级用法

文章目录 错误处理常规用法进阶用法原理 多路复用元数据负载均衡压缩数据 错误处理 gRPC 一般不在 message 中定义错误。毕竟每个 gRPC 服务本身就带一个 error 的返回值,这是用来传输错误的专用通道。gRPC 中所有的错误返回都应该是 nil 或者 由 status.Status 产…...

Redis实现登录的优化

目录 1 前言 2 实现步骤 2.1 软件环境准备 2.1.1 Redis的安装 2.1.2 在pom.xml中添加依赖 2.1.3 在application.yml中进行相关配置 2.2 StringRedisTemplate的常用方法 2.2.1 获取operations 2.2.2 主要方法 2.3 令牌主动失效机制 2.3.1 登录时将令牌存入Redis 2.…...

ROS方向第二次汇报(5)

文章目录 1.本方向内学习内容:1.1.自定义msg:1.1.1.定义msg文件:1.1.2.编辑配置文件: 1.2.自定义srv:1.2.1.定义srv文件:1.2.2.编辑配置文件: 1.3.服务通信案例实现:1.3.1.服务端实现…...

C# 浅克隆与深克隆

在C#中,浅克隆(Shallow Clone)和深克隆(Deep Clone)是两种常见的对象克隆技术,用于创建对象的新副本。 它们的主要区别在于复制对象的层次和属性的处理方式。 浅克隆(Shallow Copy)…...

Shell 正则表达式及综合案例及文本处理工具

目录 一、常规匹配 二、常用特殊字符 三、匹配手机号 四、案例之归档文件 五、案例之定时归档文件 六、Shell文本处理工具 1. cut工具 2. awk工具 一、常规匹配 一串不包含特殊字符的正则表达式匹配它自己 例子,比如说想要查看密码包含root字符串的&#x…...

React | Center 组件

在 Flutter 中有 Center 组件,效果就是让子组件整体居中,挺好用。 React 中虽然没有对应的组件,但是可以简单封装一个: index.less .container {display: flex;justify-content: center;align-items: center;align-content: ce…...

计算机二级Python考试的核心知识点总结

以下是计算机二级Python考试的核心知识点总结,结合高频考点和易错点分类整理: 1. **数据类型与运算** ▷ 不可变类型:int, float, str, tuple(重点区分list与tuple) ▷ 运算符优先级:** > * /…...

LabVIEW音频测试分析

LabVIEW通过读取指定WAV 文件,实现对音频信号的播放、多维度测量分析功能,为音频设备研发、声学研究及质量检测提供专业工具支持。 主要功能 文件读取与播放:支持持续读取示例数据文件夹内的 WAV 文件,可实时播放音频以监听被测信…...

java复习 05

我的天啊一天又要过去了,没事的还有时间!!! 不要焦虑不要焦虑,事实证明只要我认真地投入进去一切都还是来得及的,代码多实操多复盘,别叽叽喳喳胡思乱想多多思考,有迷茫前害怕后的功…...

网络爬虫一课一得

网页爬虫(Web Crawler)是一种自动化程序,通过模拟人类浏览行为,从互联网上抓取、解析和存储网页数据。其核心作用是高效获取并结构化网络信息,为后续分析和应用提供数据基础。以下是其详细作用和用途方向: …...

从代码学习深度强化学习 - 初探强化学习 PyTorch版

文章目录 前言强化学习的概念强化学习的环境强化学习中的数据强化学习的独特性总结前言 本文将带你初步了解强化学习 (Reinforcement Learning, RL) 的基本概念,并通过 PyTorch 实现一些简单的强化学习算法。强化学习是一种让智能体 (agent) 通过与环境 (environment) 的交互…...

oracle数据恢复—oracle数据库执行truncate命令后的怎么恢复数据?

oracle数据库误执行truncate命令导致数据丢失是一种常见情况。通常情况下,oracle数据库误操作删除数据只需要通过备份恢复数据即可。也会碰到一些特殊情况,例如数据库备份无法使用或者还原报错等。下面和大家分享一例oracle数据库误执行truncate命令导致…...

【物联网-ModBus-RTU

物联网-ModBus-RTU ■ 优秀博主链接■ ModBus-RTU介绍■(1)帧结构■(2)查询功能码 0x03■(3)修改单个寄存器功能码 0x06■(4)Modbus RTU 串口收发数据分析 ■ 优秀博主链接 Modbus …...

C#提取CAN ASC文件时间戳:实现与性能优化

C#提取CAN ASC文件时间戳:实现与性能优化 在汽车电子和工业控制领域,CAN总线是最常用的通信协议之一。而ASC(ASCII)文件作为CAN总线数据的标准日志格式,广泛应用于数据记录和分析场景。本文将深入探讨如何高效地从CAN…...

[BIOS]VSCode zx-6000 编译问题

前提:Python 3.6.6及以上版本安装成功,Python 3.6.6路径加到了环境变量# DEVITS工具包准备好 问题:添加环境变量 1:出现环境变量错误,“py -3” is not installed or added to environment variables #先在C:\Windows里…...

什么是预训练?深入解读大模型AI的“高考集训”

1. 预训练的通俗理解:AI的“高考集训” 我们可以将预训练(Pre-training) 形象地理解为大模型AI的“高考集训”。就像学霸在高考前需要刷五年高考三年模拟一样,大模型在正式诞生前,也要经历一场声势浩大的“题海战术”…...