K8S - Secret 的简介和使用

news2024/11/16 12:06:09

在这里插入图片描述





Secret 的定义

Kubernetes(k8s)中的 Secret 是一种用于存储敏感信息的 Kubernetes 资源对象,如密码、API 密钥、证书等。Secret 被设计为用于安全地存储和管理敏感数据,并且可以通过 Volume 或环境变量的方式将这些数据提供给 Pod 中的容器。

简单来讲, K8S 的secret 和 configmap 的作用都是存放configuration 配置数据
但是 configmap 不适合存放证书, 密码等敏感数据。
官方推荐把敏感配置 存放在 secret 中, 会更加安全, 虽然个人认为也不怎么安全





Secret 创建

跟configmap 类似
screct 也可以用如下kubeclt命令来查看创建的例子

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl create secret -h
Create a secret with specified type.

 A docker-registry type secret is for accessing a container registry.

 A generic type secret indicate an Opaque secret type.

 A tls type secret holds TLS certificate and its associated key.

Available Commands:
  docker-registry   Create a secret for use with a Docker registry
  generic           Create a secret from a local file, directory, or literal value
  tls               Create a TLS secret

Usage:
  kubectl create secret (docker-registry | generic | tls) [options]

Use "kubectl create secret <command> --help" for more information about a given command.
Use "kubectl options" for a list of global command-line options (applies to all commands).





Secret 的3个子类

由上面看出 secret 也分3个子类

  1. docker-repository 这个类别是存放docker 私服的验证token, 会保存为json 格式, 假如k8s deployment拉取的镜像是from docker 私服, 则很可能需要provide 这个 docker-repository 类别的secret
  2. tls 用于存放ssl 证书 和 passwork 等信息
  3. generic 正常的text , 密码等配置

本文主要详细介绍 generic 类型, 不会cover 其他两种





generic 类型 secret的创建

1. by kubectl command line

还是先看一下官方例子

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl create secret generic -h
Create a secret based on a file, directory, or specified literal value.

 A single secret may package one or more key/value pairs.

 When creating a secret based on a file, the key will default to the basename of the file, and the value will default to
the file content. If the basename is an invalid key or you wish to chose your own, you may specify an alternate key.

 When creating a secret based on a directory, each file whose basename is a valid key in the directory will be packaged
into the secret. Any directory entries except regular files are ignored (e.g. subdirectories, symlinks, devices, pipes,
etc).

Examples:
  # Create a new secret named my-secret with keys for each file in folder bar
  kubectl create secret generic my-secret --from-file=path/to/bar
  
  # Create a new secret named my-secret with specified keys instead of names on disk
  kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa
--from-file=ssh-publickey=path/to/id_rsa.pub
  
  # Create a new secret named my-secret with key1=supersecret and key2=topsecret
  kubectl create secret generic my-secret --from-literal=key1=supersecret --from-literal=key2=topsecret
  
  # Create a new secret named my-secret using a combination of a file and a literal
  kubectl create secret generic my-secret --from-file=ssh-privatekey=path/to/id_rsa --from-literal=passphrase=topsecret
  
  # Create a new secret named my-secret from env files
  kubectl create secret generic my-secret --from-env-file=path/to/foo.env --from-env-file=path/to/bar.env
...

这里就不一一作例子了, 选最常用那个

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl create secret generic test-sec1 --from-literal=username=u123 --from-literal=password=p123456
secret/test-sec1 created

这里的 test-sec1 是secret item的名字, 在这个item 其实里面创建了2个 secret 对象
分别是
username:u123
password:p12345

注意, 如果value 包含特殊字符, 则需要用引号包住, 否则base64 encode 会有gap

2. by yaml

格式

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  username: <base64-encoded-username>
  password: <base64-encoded-password>

注意的是, secret里的值都需要 base64 encoded之后才写入yaml文件, 但是base64 encoded 的text 是十分容易decoded, 所以建议密码还是要先加密再encoded 写入





Secret 的查看

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl get secret 
NAME                  TYPE                                  DATA   AGE
default-token-7khb9   kubernetes.io/service-account-token   3      175d
test-sec1             Opaque                                2      25m
gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ 

注意这里的Opaque 就是 generic的意思, Data 列2 是有连个子项(username , password)

用 Kubectl describe secret 只能看到size 信息

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl describe secret test-sec1
Name:         test-sec1
Namespace:    default
Labels:       <none>
Annotations:  <none>

Type:  Opaque

Data
====
password:  7 bytes
username:  4 bytes

用 kubectl get secret xxx -o yaml 可以查看encoded 后的值

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl get secret test-sec1 -o yaml
apiVersion: v1
data:
  password: cDEyMzQ1Ng==
  username: dTEyMw==
kind: Secret
metadata:
  creationTimestamp: "2024-08-17T13:47:38Z"
  name: test-sec1
  namespace: default
  resourceVersion: "6132863"
  uid: 2a027099-090b-478b-b460-e42991a50c62
type: Opaque

很方便地 decoded 出来真正的值

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ echo cDEyMzQ1Ng== | base64 --decode
p123456

所以说也不是很安全





Secret 的使用

例子介绍

这里我们用springboot 访问mysql的用户名和密码作例子

原本 cloud order service 的配置文件是这样的
application-prod.yml

...
spring:
  datasource:
    url: jdbc:mysql://192.168.0.42:3306/demo_cloud_order?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
    username: cloud_order
    password: ENC(xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)
    driver-class-name: com.mysql.cj.jdbc.Driver
...

我们增加1个yaml 文件作为例子
application-k8sprod

...
spring:
  datasource:
    url: jdbc:mysql://192.168.0.42:3306/demo_cloud_order?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true
    driver-class-name: com.mysql.cj.jdbc.Driver
...

吧user name 和 密码去掉了
那么怎么启动这个springboot service呢, 当然是在启动参数中传入



方法1, 吧secret map 到 环境变量

创建 secret 包含db 的username 和 password (加密后的)

这里用yaml方式

cloud-order-db-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: cloud-order-db-secret
type: Opaque
data:
  # echo cloud-order | base64
  username: Y2xvdWQtb3JkZXIK
  password: RU5DKE9KaDRYVGFXejFixxxxxxxxxxxxx

执行

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl apply -f cloud-order-db-secret.yaml 
secret/cloud-order-db-secret created



修改deployment yaml

deployment-cloud-order-with-secret-command-notwork.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels: # label of this deployment
    app: cloud-order # custom defined
    author: nvd11
  name: deployment-cloud-order # name of this deployment
  namespace: default
spec:
  replicas: 3            # desired replica count, Please note that the replica Pods in a Deployment are typically distributed across multiple nodes.
  revisionHistoryLimit: 10 # The number of old ReplicaSets to retain to allow rollback
  selector: # label of the Pod that the Deployment is managing,, it's mandatory, without it , we will get this error 
            # error: error validating data: ValidationError(Deployment.spec.selector): missing required field "matchLabels" in io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector ..
    matchLabels:
      app: cloud-order
  strategy: # Strategy of upodate
    type: RollingUpdate # RollingUpdate or Recreate
    rollingUpdate:
      maxSurge: 25% # The maximum number of Pods that can be created over the desired number of Pods during the update
      maxUnavailable: 25% # The maximum number of Pods that can be unavailable during the update
  template: # Pod template
    metadata:
      labels:
        app: cloud-order # label of the Pod that the Deployment is managing. must match the selector, otherwise, will get the error Invalid value: map[string]string{"app":"bq-api-xxx"}: `selector` does not match template `labels`
    spec: # specification of the Pod
      containers:
      - image: europe-west2-docker.pkg.dev/jason-hsbc/my-docker-repo/cloud-order:1.0.2 # image of the container
        imagePullPolicy: Always
        name: container-cloud-order
        command: ["bash"]
        # does not work, as the password format is ENV(xxxxx) , and the java -jar command could not handle (),  after I added double quotes "ENV(xxxx)", service failed to start due to db password error
        # unless I set the plain text password to secret , but I don't think it's secure enough
        args: 
          - "-c"
          - |
            java -jar -Dserver.port=8080 app.jar --spring.profiles.active=$APP_ENVIRONMENT --spring.datasource.username=$DB_USER --spring.datasource.password=$DB_PASSWORD 
        env: # set env varaibles
        - name: APP_ENVIRONMENT # name of the environment variable
          value: k8sprod # value of the environment variable
        - name: APP_TAG 
          valueFrom: # value from config map
            configMapKeyRef: 
              name: cloud-order-app-tag-config # name of the configMap item
              key: APP_TAG # key from the config map item
        - name: DB_USER
          valueFrom: # value from secret
            secretKeyRef:
              name: cloud-order-db-secret
              key: username
        - name: DB_PASSWORD
          valueFrom: # value from secret
            secretKeyRef:
              name: cloud-order-db-secret
              key: password
            
            
      restartPolicy: Always # Restart policy for all containers within the Pod
      terminationGracePeriodSeconds: 10 # The period of time in seconds given to the Pod to terminate gracefully

但是实际上这个方法对这个case 不work

因为java -jar 无法处理 ENV(XXX)
例如

gateman@MoreFine-S500:~/tmp$ java -jar -Dserver.port=8085 app.jar --spring.profiles.active=k8sprod --spring.datasource.username=cloud-order --spring.datasource.password=ENC(OJh4XTaWz1beLRY/1cMxxxx)
bash: syntax error near unexpected token `('

不能正确地转义括号

当我加上"" 双引号包住ENV()
则启动失败, 报错db 密码错误
我暂时无法解决这个问题, 除非我把明文密码放入secret , 不使用ENV() , 但是上面说过了, 把明文密码放入secret 我认为不够安全, 很容易decoded 出来




方法2, 吧secret 保存到文件

前提是其实
java 启动spring boot 命令有1个特性, 可以额外指定包含另1个配置文件

java -jar -Dserver.port=8085 -Dspring.config.additional-location=db-config.yaml app.jar --spring.profiles.active=k8sprod

注意这里的 spring.config.additional-location 必须用 -D 作为VM 参数传入, 而不是 --spring.boot 参数传入

所以我们的方向是吧username 和 password 的配置写入到1个卷中




创建 secret 包含db 的username 和 password (加密后的)

cloud-order-db-secret-file.yaml

apiVersion: v1
kind: Secret
metadata:
  name: cloud-order-db-secret-file
type: Opaque
data:
  # atasource:
  #   username: cloud_order
  #   password: ENC(OJh4XTaWz1beLRY/1cM4Xaxxx)
  dbconfig: c3ByaW5nOgogIGRhdGFzb3VyY2U6Cxxxx

注意这里的encoded 码是 原本的格式 , 必须符合spring 的配置




修改 deployment yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels: # label of this deployment
    app: cloud-order # custom defined
    author: nvd11
  name: deployment-cloud-order # name of this deployment
  namespace: default
spec:
  replicas: 3            # desired replica count, Please note that the replica Pods in a Deployment are typically distributed across multiple nodes.
  revisionHistoryLimit: 10 # The number of old ReplicaSets to retain to allow rollback
  selector: # label of the Pod that the Deployment is managing,, it's mandatory, without it , we will get this error 
            # error: error validating data: ValidationError(Deployment.spec.selector): missing required field "matchLabels" in io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector ..
    matchLabels:
      app: cloud-order
  strategy: # Strategy of upodate
    type: RollingUpdate # RollingUpdate or Recreate
    rollingUpdate:
      maxSurge: 25% # The maximum number of Pods that can be created over the desired number of Pods during the update
      maxUnavailable: 25% # The maximum number of Pods that can be unavailable during the update
  template: # Pod template
    metadata:
      labels:
        app: cloud-order # label of the Pod that the Deployment is managing. must match the selector, otherwise, will get the error Invalid value: map[string]string{"app":"bq-api-xxx"}: `selector` does not match template `labels`
    spec: # specification of the Pod
      containers:
      - image: europe-west2-docker.pkg.dev/jason-hsbc/my-docker-repo/cloud-order:1.0.2 # image of the container
        imagePullPolicy: Always
        name: container-cloud-order
        command: ["bash"]
        args: 
          - "-c"
          - |
            java -jar -Dserver.port=8080 -Dspring.config.additional-location=/app/config/db-config.yaml app.jar --spring.profiles.active=$APP_ENVIRONMENT
        env: # set env varaibles
        - name: APP_ENVIRONMENT # name of the environment variable
          value: k8sprod # value of the environment variable
        - name: APP_TAG 
          valueFrom: # value from config map
            configMapKeyRef: 
              name: cloud-order-app-tag-config # name of the configMap item
              key: APP_TAG # key from the config map item
        - name: DB_USER
          valueFrom: # value from secret
            secretKeyRef:
              name: cloud-order-db-secret
              key: username
        - name: DB_PASSWORD
          valueFrom: # value from secret
            secretKeyRef:
              name: cloud-order-db-secret
              key: password
        volumeMounts: # volume mount
          - name: db-config
            mountPath: /app/config
      volumes:
        - name: db-config
          secret:
            secretName: cloud-order-db-secret-file  
            items:
              - key: dbconfig
                path: db-config.yaml
            
            
      restartPolicy: Always # Restart policy for all containers within the Pod
      terminationGracePeriodSeconds: 10 # The period of time in seconds given to the Pod to terminate gracefully

注意上面有几点

  1. command 容器启动命令被改成 java -jar -Dserver.port=8080 -Dspring.config.additional-location=/app/config/db-config.yaml app.jar --spring.profiles.active=$APP_ENVIRONMENT
  2. 把 secret的内容写入 到/app/config/db-config




检查和测试
gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl apply -f deployment-cloud-order-with-secret.yaml 
deployment.apps/deployment-cloud-order created

首先部署

再进入容器, 查看/app/config/db-config.yaml 是否被生成

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ kubectl exec -it deployment-cloud-order-588c9444dc-7cphs /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl exec [POD] -- [COMMAND] instead.
bash-4.4# cat /app/config/db-config.yaml 
spring:
  datasource:
    username: cloud_order
    password: ENC(OJh4XTaWz1beLRY/1cM4Xa6IP/mrxxxxxx)

正确生成

测试接口:

gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ curl http://www.jp-gcp-vms.cloud:8085/cloud-order/actuator/info | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1922    0  1922    0     0   3616      0 --:--:-- --:--:-- --:--:--  3612
{
  "app": "Cloud Order Service",
  "appEnvProfile": "k8sprod",
  "version": "1.0.2",
  "hostname": "deployment-cloud-order-588c9444dc-cjtkv",
  "dbUrl": "jdbc:mysql://192.168.0.42:3306/demo_cloud_order?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true",
  "description": "This is a simple Spring Boot application to for cloud order...",
  "SystemVariables": {
    "PATH": "/usr/java/openjdk-17/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "CLUSTERIP_CLOUD_ORDER_SERVICE_HOST": "10.98.117.97",
    "CLUSTERIP_BQ_API_SERVICE_SERVICE_PORT": "8080",
    "KUBERNETES_PORT": "tcp://10.96.0.1:443",
    "DB_USER": "cloud-order\n",
    "JAVA_HOME": "/usr/java/openjdk-17",
    "KUBERNETES_SERVICE_HOST": "10.96.0.1",
    "LANG": "C.UTF-8",
    "CLUSTERIP_CLOUD_ORDER_PORT": "tcp://10.98.117.97:8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT_8080_TCP": "tcp://10.100.68.154:8080",
    "CLUSTERIP_CLOUD_ORDER_PORT_8080_TCP": "tcp://10.98.117.97:8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT_8080_TCP_PROTO": "tcp",
    "PWD": "/app",
    "JAVA_VERSION": "17.0.2",
    "_": "/usr/java/openjdk-17/bin/java",
    "CLUSTERIP_CLOUD_ORDER_PORT_8080_TCP_ADDR": "10.98.117.97",
    "KUBERNETES_PORT_443_TCP": "tcp://10.96.0.1:443",
    "KUBERNETES_PORT_443_TCP_ADDR": "10.96.0.1",
    "CLUSTERIP_CLOUD_ORDER_PORT_8080_TCP_PORT": "8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT": "tcp://10.100.68.154:8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT_8080_TCP_PORT": "8080",
    "KUBERNETES_PORT_443_TCP_PROTO": "tcp",
    "APP_ENVIRONMENT": "k8sprod",
    "KUBERNETES_SERVICE_PORT": "443",
    "CLUSTERIP_CLOUD_ORDER_SERVICE_PORT": "8080",
    "CLUSTERIP_BQ_API_SERVICE_PORT_8080_TCP_ADDR": "10.100.68.154",
    "APP_TAG": "cloud-order-app-tag",
    "HOSTNAME": "deployment-cloud-order-588c9444dc-cjtkv",
    "CLUSTERIP_CLOUD_ORDER_PORT_8080_TCP_PROTO": "tcp",
    "CLUSTERIP_BQ_API_SERVICE_SERVICE_HOST": "10.100.68.154",
    "KUBERNETES_PORT_443_TCP_PORT": "443",
    "KUBERNETES_SERVICE_PORT_HTTPS": "443",
    "SHLVL": "1",
    "HOME": "/root",
    "DB_PASSWORD": "ENC(OJh4XTaWz1beLRY/1cM4Xa6IP/mrKgx2CdVRysJl+BZ/+7eHswcEzQWFF1PR/Hhl)"
  }
}
gateman@MoreFine-S500:~/projects/coding/k8s-s/service-case/cloud-order$ curl http://www.jp-gcp-vms.cloud:8085/cloud-order/actuator/health | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   364    0   364    0     0    735      0 --:--:-- --:--:-- --:--:--   736
{
  "status": "UP",
  "components": {
    "db": {
      "status": "UP",
      "details": {
        "database": "MySQL",
        "validationQuery": "isValid()"
      }
    },
    "diskSpace": {
      "status": "UP",
      "details": {
        "total": 20891439104,
        "free": 12675047424,
        "threshold": 10485760,
        "path": "/app/.",
        "exists": true
      }
    },
    "livenessState": {
      "status": "UP"
    },
    "ping": {
      "status": "UP"
    },
    "readinessState": {
      "status": "UP"
    }
  },
  "groups": [
    "liveness",
    "readiness"
  ]
}

测试通过!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2049889.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32软件I2C通信详解

目录 18.[江协]I2C通信详解 I2C通信介绍 软件I2C和硬件I2C的区别 I2C硬件电路规定 I2C软件设计&#xff08;时序基本单元&#xff09; 起始条件与终止条件 主机发送一个字节 的时序单元 主机接收一个字节 的时序单元 主机/从机 应答 基本单元 I2C完整时序&#xff08…

【Python单元测试】学习笔记1

文章目录 01-单元测试基础什么是单元测试常用的文件结构运行单元测试 02. 断言函数03. Test Fixtures什么是Test Fixtures模块级别的Fixtures类级别的Fixtures方法级别的Fixtures 04.Mock python单元测试学习笔记1&#xff1a;https://blog.csdn.net/qq_42761751/article/detai…

kali实用工具之NC

NC&#xff08;netcat&#xff09;被称为网络工具中的瑞士军刀&#xff0c;体积小巧&#xff0c;但功能强大。Nc主要功能是可以在两台设备上面相互交互&#xff0c;即侦听模式/传。 1、传输数据 在kali开启监听6666端口号&#xff1a; 在centos连接kali的6666端口号&#xff1a…

LeetCode --- 410周赛

题目列表 3248. 矩阵中的蛇 3249. 统计好节点的数目 3250. 单调数组对的数目 I 3251. 单调数组对的数目 II 一、矩阵中的蛇 只要按照题目要求模拟即可&#xff0c;代码如下 class Solution { public:int finalPositionOfSnake(int n, vector<string>& commands…

Camera Link 与 NI PCIe-1433 的工作原理及应用

Camera Link 是一种专为工业和科学成像应用设计的串行通信协议标准。它的主要优势在于能够提供高带宽、高可靠性的图像数据传输&#xff0c;并且具备灵活的配置选项&#xff0c;适用于多种不同的摄像机类型。Camera Link 的标准使得它在需要高速度、高分辨率图像传输的应用中得…

Java流程控制08:continue、break、goto

本节内容视频链接&#xff1a;https://www.bilibili.com/video/BV12J41137hu?p43&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5https://www.bilibili.com/video/BV12J41137hu?p43&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 java中break和continue的作用和区别 在J…

通过kuboard界面配置ingress

安装 Ingress Controller&#xff0c;Kuboard 为您提供了一种快速安装 ingress-nginx 的方法&#xff0c;步骤如下所示。 1&#xff09;导航到集群的 集群管理 --> 网络 --> IngressClass 列表页&#xff0c;如下图所示&#xff1a; 2&#xff09;点击图中的 安装 Ingre…

WordPress美化节日灯笼插件,适合春节的时候使用

源码介绍&#xff1a; WordPress美化节日灯笼插件&#xff0c;适合每年过年的时候安在网站上使用&#xff0c;这款插件可以备用着&#xff0c;一款WordPress节日灯笼美化插件&#xff0c;可以给网页自动加一个灯笼效果使用说明&#xff1a;到网站WP后台 - 插件 - 安装插件 - 上…

可复制拖拽流程图

功能&#xff1a;如上图所示&#xff0c;从左侧拖拽源拖拽出模块后&#xff0c;在右侧显示。 源码&#xff1a;

【OpenCV 】插值的方法原理,图片缩放,矫正,边界填充

图像旋转 缩放 计算机中的图像是以数组的方式储存&#xff0c;每个位置储存了像素点的像素值。对图像进行旋转缩放&#xff0c;就是对数组进行操作&#xff0c;乘以对应的矩阵&#xff0c;进行空间变换&#xff0c;而矩阵的行列式的值&#xff0c;就是缩放的倍数。 进行缩放旋…

stm32智能颜色送餐小车(ESP8266WIFI模块、APP制作、物联网模型建立、MQTTFX)

大家好啊&#xff0c;我是情谊&#xff0c;今天我们来介绍一下我最近设计的stm32产品&#xff0c;我们在今年七月份的时候参加了光电设计大赛&#xff0c;我们小队使用的就是stm32的智能送餐小车&#xff0c;虽然止步于省赛&#xff0c;但是还是一次成长的经验吧&#xff0c;那…

在IntelliJ IDEA中使用Git推送项目

去gitee网站注册用户 gitee网站地址:https://gitee.com/ github网站地址:https://github.com/ 一、创建仓库 以下以gitee为例进行介绍&#xff0c;github操作雷同。 1、创建仓库 点击页面右上方的"“并选择"创建仓库” 2、设置仓库相关信息 首先输入仓库名&…

时序预测|基于PO-TCN-BiGRU的数据单变量和多变量时序预测Matlab程序 含基础模型对比TCN-BiGRU

时序预测|基于PO-TCN-BiGRU的数据单变量和多变量时序预测Matlab程序 含基础模型对比TCN-BiGRU 文章目录 前言时序预测|基于PO-TCN-BiGRU的数据单变量和多变量时序预测Matlab程序 含基础模型对比TCN-BiGRU 一、PO-TCN-BiGRU模型1. 时间卷积网络 (TCN)2. 双向门控循环单元 (BiGRU…

Modbus-RTU使用过程中的问题

此程序是在visual studio 2005的MFC程序中执行的&#xff0c;通过引入ModbusRTU.dll进行程序的编程&#xff0c;通过Dependency Walker工具查看ModbusRTU.dll中的静态函数如下&#xff1a; 在ModbusRTU.h文件中 MOD_API WORD RTUReadDiscreteInputs(BYTE nSlaveAddress, WORD …

接口自动化测试,介入时间以及整个流程规范是怎样的?

最近&#xff0c;小编身边有人提出一个问题&#xff1a; 背景 公司的接口自动化是从开发提测的时候开始用例设计开发的&#xff08;因为我们公司没有接口文档&#xff0c;只能等开发完成后自己抓包&#xff09;&#xff0c;也就是接口自动化开发和功能测试是同时进行的&#…

Ubuntu 基础使用

一、下载Vmware workstation 和ubuntu映像文件 二、安装虚拟机 三、安装完成之后打开程序&#xff0c;选择创建新的虚拟机 选择映射文件 编辑信息 这里尽量选择一个特定的位置 根据自己的要求设定 设置完成后等待自己安装不需要进行操作 出现登录页面表示安装成功 四、基本指令…

K8S系列——(一)、Ubuntu上安装Helm

在使用K8S搭建集群服务时&#xff0c;有时候需要用到Helm&#xff08;一个用于Kubernetes应用管理的工具&#xff09;&#xff0c;下面是在Ubuntu上安装Helm的过程。 1.更新系统软件包列表 sudo apt-get update2.安装必要的依赖项 sudo apt-get install apt-transport-https…

怎么在网络攻击中屹立不倒

在当今蓬勃发展的网络游戏产业中&#xff0c;服务器安全无疑是企业生存与发展的基石。面对互联网环境中无处不在的DDoS&#xff08;分布式拒绝服务&#xff09;与CC&#xff08;挑战碰撞&#xff09;攻击威胁&#xff0c;游戏服务器的防御能力与高效处理能力显得尤为重要。相较…

11.2.0.4 RAC 节点1重做操作系统后如何复原

环境描述&#xff1a;Redhat7.9 11.2.0.4 RAC 双节点 实验背景 群里有大佬在交流RAC中1个节点操作系统坏了如何修复&#xff0c;故有了该实验。 在正常的生产环境当中&#xff0c;有时候会遇到主机磁盘以及其他硬件故障导致主机OS系统无法启动&#xff0c;或者OS系统本身故障…

C语言 | Leetcode C语言题解之第342题4的幂

题目&#xff1a; 题解&#xff1a; bool isPowerOfFour(int n) {return n > 0 && (n & (n - 1)) 0 && n % 3 1; }