【GitOps系列】自动化构建Image

news2024/11/26 12:26:28

文章目录

      • 使用 GitHub Action 构建镜像
      • 使用 GitLab CI 构建镜像
      • 使用 Tekton 构建镜像
        • Tekton组件安装
        • Tekton 简介
        • 创建 Tekton Pipeline
          • 创建 Task
          • 创建 Pipeline
          • 创建 EventListener
          • 创建 TriggerTemplate
          • 创建 Service Account 和 PVC
          • 设置 Secret
        • 创建 GitHub Webhook
        • 触发 Pipeline
      • 使用 Harbor 搭建企业级镜像仓库
        • 在 Tekton Pipeline 中使用 Harbor

使用 GitHub Action 构建镜像

在这里插入图片描述
Workflow
Workflow 也叫做工作流。其实,GitHub Action 本质上是一个是一个 CI/CD 工作流,要使用工作流,我们首先需要先定义它。和 K8s Manifest 一样,GitHub Action 工作流是通过 YAML 来描述的,你可以在任何 GitHub 仓库创建 .github/workflows 目录,并创建 YAML 文件来定义工作流。
所有在 .github/workflows 目录创建的工作流文件,都将被 GitHub 自动扫描。在工作流中,通常我们会进一步定义 Event、Job 和 Step 字段,它们被用来定义工作流的触发时机和具体行为。
Event
Event 从字面上的理解是“事件”的意思,你可以简单地把它理解为定义了“什么时候运行工作流”,也就是工作流的触发器。
在定义自动化构建镜像的工作流时,我们通常会把 Event 的触发器配置成“当指定分支有新的提交时,自动触发镜像构建”。
Jobs
Jobs 的字面意思是一个具体的任务,它是一个抽象概念。在工作流中,它并不能直接工作,而是需要通过 Step 来定义具体的行为。此外,你还可以为 Job 定义它的运行的环境,例如 ubuntu。
在一个 Workflow 当中,你可以定义多个 Job,多个 Job 之间可以并行运行,也可以定义相互依赖关系。在自动构建镜像环节,通常我们只需要定义一个 Job 就够了,所以在上面的示意图中,我只画出了一个 Job。
Step
Step 隶属于 Jobs,它是工作流中最小的粒度,也是最重要的部分。通常来说,Step 的具体行为是执行一段 Shell 来完成一个功能。在同一个 Job 里,一般我们需要定义多个 Step 才能完成一个完整的 Job,由于它们是在同一个环境下运行的,所以当它们运行时,就等同于在同一台设备上执行一段 Shell。
以自动构建镜像为例,我们可能需要在 1 个 Job 中定义 3 个 Step。

  • Step1,克隆仓库的源码。
  • Step2,运行 docker build 来构建镜像。
  • Step3,推送到镜像仓库。

实现的效果:

当我们向 Main 分支推送新的提交时,GitHub Action 工作流将会被自动触发,工作流会自动构建 frontend 和 backend 镜像,并且会使用当前的 short commit id 作为镜像的 Tag 推送到 Docker Hub 中。
这意味着,每一个提交都会生成一个 Docker 镜像,实现了代码和制品的对应关系。 这种对应关系给我们带来了非常大的好处,例如当我们要回滚或更新应用时,只需要找到代码的 commit id 就能够找到对应的镜像版本。
在这里插入图片描述

使用 GitLab CI 构建镜像

GitLab CI 是通过在仓库根目录创建 .gitlab-ci.yml 文件来定义流水线的,这和 GitHub 有明显的差异。.gitlab-ci.yml 文件定义的内容也相对简单,它基本上和我们在本地构建镜像所运行的命令以及顺序是一致的。
此外,相比较 GitHub Action Workflow,GitLab CI 省略了触发器和检出代码的配置步骤,并且,在 GitLab CI 中我们是通过 DiND 的方式来运行流水线的,也就是在容器的运行环境下启动另一个容器来运行流水线,而 GitHub Action 则是通过虚拟机的方式来运行流水线。
和 GitHub Action 相比较,它们除了流水线文件内容不一样以外,其他的操作例如创建 GitLab 仓库、创建 Docker Hub Secret 以及创建 GitLab CI Variables 等步骤都是差不多的。
最终,当我们有新的推送到仓库时,GitLab CI 将运行自动构建镜像的流水线,并且每次提交的 commit id 都会对应一个镜像版本,和 GitHub Action Workflow 一样, 也实现了代码版本和制品版本的对应关系。

使用 Tekton 构建镜像

自动构建镜像的自托管方案: 使用 Tekton 来自动构建镜像。 Tekton 是一款基于 Kubernetes 的 CI/CD 开源产品,如果有一个 Kubernetes 集群,那么利用 Tekton 直接在 Kubernetes 上构建镜像是一个不错的选择。

Tekton组件安装

官网:https://tekton.dev/docs/

kubernetes版本要求:>= 1.24
1.安装 Tekton Operator
kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml

2.安装 Tekton Dashboard
kubectl apply --filename https://storage.googleapis.com/tekton-releases/dashboard/latest/release.yaml

3.安装 Tekton Trigger 和 Tekton Interceptors 组件
kubectl apply --filename \
https://storage.googleapis.com/tekton-releases/triggers/latest/release.yaml
kubectl apply --filename \
https://storage.googleapis.com/tekton-releases/triggers/latest/interceptors.yaml

~# kubectl wait --for=condition=Ready pods --all -n tekton-pipelines --timeout=300s
pod/tekton-dashboard-6ddf4d8556-mdszf condition met
pod/tekton-pipelines-controller-68fb8c9df6-cnxkz condition met
pod/tekton-pipelines-webhook-b54b6d464-9hff9 condition met
pod/tekton-triggers-controller-5969f786d6-zfk2f condition met
pod/tekton-triggers-core-interceptors-77d6499b44-h9zxp condition met
pod/tekton-triggers-webhook-67559d98cf-l2q6v condition met

4.Traefik安装
参考链接: http://t.csdn.cn/gYNGH

5.暴露 Tekton Dashboard
cat tekton-ingressroute.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: tekton-dashboard
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`tekton.k8s.local`)
    kind: Rule
    services:
    - name: tekton-dashboard
      port: 9097

在这里插入图片描述

Tekton 简介

在这里插入图片描述

【EventListener】
EventListener 顾名思义是一个事件监听器,它是外部事件的入口。EventListener 通常以 HTTP 的方式对外暴露,此处会在 GitHub 创建 WebHook 来调用 Tekton 的 EventListener,使它能接收到仓库推送事件。

【TriggerTemplate】
当 EventListener 接收到外部事件之后,它会调用 Trigger 也就是触发器,而 TriggerTemplate 是用来定义接收到事件之后需要创建的 Tekton 资源的,例如创建一个 PipelineRun 对象来运行流水线。此处会使用 TriggerTemplate 来创建 PipelineRun 资源。

【Step】
Step 是流水线中的一个具体的操作,例如构建和推送镜像操作。Step 接收镜像和需要运行的 Shell 脚本作为参数,Tekton 将会启动镜像并执行 Shell 脚本。

【Task】
Task 是一组有序的 Step 集合,每一个 Task 都会在独立的 Pod 中运行,Task 中不同的 Step 将在同一个 Pod 不同的容器内运行。

【Pipeline】
Pipeline 是 Tekton 中的一个核心组件,它是一组 Task 的集合,Task 将组成一组有向无环图(DAG),Pipeline 会按照 DAG 的顺序来执行。

【PipelineRun】
PipelineRun 实际上是 Pipeline 的实例化,它负责为 Pipeline 提供输入参数,并运行 Pipeline。例如,两次不同的镜像构建操作对应的就是两个不同的 PipelineRun 资源。

创建 Tekton Pipeline

此次Tekton流水线实现的效果~
在这里插入图片描述

当我们向 GitHub 推送代码时,GitHub 将以 HTTP 请求的方式通知集群内的 Tekton 触发器,触发器通过 Traefik ingressroute或者Ingress-Nginx 对外暴露,当触发器接收到来自 GitHub 的事件推送时,将通过 TriggerTemplate 来创建 PipelineRun 运行 Pipeline,最终实现镜像的自动构建和推送。

创建 Task

在创建 Pipeline 之前,需要先创建两个 Task,这两个 Task 分别负责“检出代码”还有“构建和推送镜像”。

$ kubectl apply -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/gitops/main/ci/18/tekton/task/git-clone.yaml
这个 Task 是 Tekton 官方提供的插件,它和 GitHub Action 的 checkout 插件有一点类似,主要作用是检出代码

创建构建和推送镜像的 Task:
$ kubectl apply -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/gitops/main/ci/18/tekton/task/docker-build.yaml

Task关键内容如下:
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: docker-socket
spec:
  workspaces:
    - name: source
  params:
    - name: image
      description: Reference of the image docker will produce.
    ......
  steps:
    - name: docker-build
      image: docker:stable
      env:
        ......
        - name: IMAGE
          value: $(params.image)
        - name: DOCKER_PASSWORD
          valueFrom:
            secretKeyRef:
              name: registry-auth
              key: password
        - name: DOCKER_USERNAME
          valueFrom:
            secretKeyRef:
              name: registry-auth
              key: username
      workingDir: $(workspaces.source.path)
      script: |
        cd $SUBDIRECTORY
        docker login $REGISTRY_URL -u $DOCKER_USERNAME -p $DOCKER_PASSWORD
        if [ "${REGISTRY_URL}" = "docker.io" ] ; then
          docker build --no-cache -f $CONTEXT/$DOCKERFILE_PATH -t $DOCKER_USERNAME/$IMAGE:$TAG $CONTEXT
          docker push $DOCKER_USERNAME/$IMAGE:$TAG
          exit
        fi
        docker build --no-cache -f $CONTEXT/$DOCKERFILE_PATH -t $REGISTRY_URL/$REGISTRY_MIRROR/$IMAGE:$TAG $CONTEXT
        docker push $REGISTRY_URL/$REGISTRY_MIRROR/$IMAGE:$TAG
      volumeMounts: # 共享 docker.socket
        - mountPath: /var/run/
          name: dind-socket
  sidecars: #sidecar 提供 docker daemon
    - image: docker:dind
      ......
-------------------------------------------------------------------------
spec.params 字段用来定义变量,并最终由 PipelineRun 提供具体的值。
spec.steps 字段用来定义具体的执行步骤,例如,这里使用 docker:stable 镜像创建了容器,并将 spec.params 定义的变量以 ENV 的方式传递到容器内部,
其中 DOCKER_PASSWORD 和 DOCKER_USERNAME 两个变量来源于 Secret,将在后续创建。
spec.steps[0].script 字段定义了具体执行的命令,这里执行了 docker login 登录到 Docker Hub,并且使用了 docker build 和 docker push 来构建和推送镜像。我们对 Docker Hub 和其他镜像仓库做了区分,以便使用不同的 TAG 命名规则。
spec.sidecars 字段为容器提供 Docker daemon,它使用的镜像是 docker:dind。
创建 Pipeline

创建完 Task 之后,由于它们实现的具体功能是独立的,所以需要将他们联系起来。也就是说,我们希望 Pipeline 先克隆代码,再构建和推送镜像。所以,下面需要创建 Pipeline 来引用这两个 Task。

$ kubectl apply -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/gitops/main/ci/18/tekton/pipeline/pipeline.yaml

pipeline介绍:
apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: github-trigger-pipeline
spec:
  workspaces:
    - name: pipeline-pvc
    ......
  params:
    - name: subdirectory # 为每一个 Pipeline 配置一个 workspace,防止并发错误
      type: string
      default: ""
    - name: git_url
    ......
  tasks:
    - name: clone
      taskRef:
        name: git-clone
      workspaces:
        - name: output
          workspace: pipeline-pvc
        - name: ssh-directory
          workspace: git-credentials
      params:
        - name: subdirectory
          value: $(params.subdirectory)
        - name: url
          value: $(params.git_url)
    - name: build-and-push-frontend
      taskRef:
        name: docker-socket
      runAfter:
        - clone
      workspaces:
        - name: source
          workspace: pipeline-pvc
      params:
        - name: image
          value: "frontend"
        ......
    - name: build-and-push-backend
      taskRef:
        name: docker-socket
      runAfter:
        - clone
      workspaces:
        - name: source
          workspace: pipeline-pvc
      params:
        - name: image
          value: "backend"
        ......

首先,spec.workspaces 定义了一个工作空间。还记得我们提到的每一个 Task 都会在独立的 Pod 中运行吗?那么不同的 Task 如何共享上下文呢?答案就是 workspaces。实际上它是一个 PVC 持久化卷,这个 PVC 将会在 Pod 之间复用,这就让下游 Task 可以读取到上游 Task 写入的数据(比如克隆的代码)。
spec.params 定义了 Pipeline 的参数,参数的传递顺序是:PipelineRun->Pipeline->Task。
spec.tasks 定义了 Pipeline 引用的 Task,例如在这里分别引用了 git-clone 和 docker-socket 两个 Task,并且都指定了同一个 workspaces pipeline-pvc,然后指定了 params 向 Task 传递了参数值。
在 build-and-push-frontend 和 build-and-push-backend Task 中,都指定了 runAfter 字段,它的含义是等待 clone Task 执行完毕后再运行。
所以,Pipeline 对 Task 的引用就形成了一个有向无环图(DAG),在这个 Pipeline 中,首先会检出源码,然后以并行的方式同时构建前后端镜像。

创建 EventListener

创建完 Pipeline 之后,工作流实际上就已经定义好了。但是我们并不希望手动来运行它,我们希望通过 GitHub 来自动触发它。所以,接下来需要创建 EventListener 来获得一个能够监听外部事件的服务。

$ kubectl apply -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/gitops/main/ci/18/tekton/trigger/github-event-listener.yaml

EventListener 的具体作用:
接收来自 GitHub 的 Webhook 调用,并将 Webhook 的参数和TriggerTemplate 定义的参数对应起来,以便将参数值从 Webhook 一直传递到 PipelineRun。

暴露 EventListener

cat listener-ingressroute.yaml 
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
  name: el-github-listener
spec:
  entryPoints:
    - web
  routes:
    - match: Host(`xxxxxx`) && PathPrefix(`/hooks`)
      kind: Rule
      services:
        - name: el-github-listener
          port: 8080
创建 TriggerTemplate

EventListener 并不能独立工作,它还需要一个助手,那就是 TriggerTemplate。TriggerTemplate 是真正控制 Pipeline 启动的组件,它负责创建 PipelineRun。

$ kubectl apply -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/gitops/main/ci/18/tekton/trigger/github-trigger-template.yaml
创建 Service Account 和 PVC

由于触发器并没有具体的执行用户,所以我们还需要为触发器配置权限,也就是创建 Service Account。同时,我们也可以一并创建用于共享 Task 之间上下文的 PVC。这一步操作可以提前操作。

$ kubectl apply -f https://ghproxy.com/https://raw.githubusercontent.com/lyzhang1999/gitops/main/ci/18/tekton/other/service-account.yaml
设置 Secret

需要为 Tekton 提供一些凭据信息,例如 Docker Hub Token、GitHub Webhook Secret 以及用于检出私有仓库的私钥信息。

$ kubectl apply -f secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: registry-auth
  annotations:
    tekton.dev/docker-0: https://docker.io
type: kubernetes.io/basic-auth
stringData:
  username: "" # docker username
  password: "" # docker hub token

---
# github webhook token secret
apiVersion: v1
kind: Secret
metadata:
  name: github-secret
type: Opaque
stringData:
  secretToken: "webhooksecret"
---
apiVersion: v1
kind: Secret
metadata:
  name: git-credentials
data:
  id_rsa: LS0tLS......
  known_hosts: Z2l0aHViLm......
  config: SG9zd......


- 将 stringData.username 替换为你的 Docker Hub 的用户名。
- 将 stringData.password 替换为你的 Docker Hub Token
- 将 data.id_rsa 替换为你本地 ~/.ssh/id_rsa 文件的 base64 编码内容,这将会为 Tekton 提供检出私有仓库的权限
- 将 data.known_hosts 替换为你本地 ~/.ssh/known_hosts 文件的 base64 编码内容,你可以通过 $ cat ~/.ssh/known_hosts | grep "github" | base64 命令来获取。
- 将 data.config 替换为你本地 ~/.ssh/config 文件的 base64 编码内容

创建 GitHub Webhook

打开GitHub 创建的 kubernetes-example 仓库,进入“Settings”页面,点击左侧的“Webhooks”菜单,在右侧的页面中按照下图进行配置。
在这里插入图片描述

触发 Pipeline

现在我们向仓库提交一个空的 commit 来触发 Pipeline,测试验证一下

➜ kubernetes-example (main) ✔ git commit --allow-empty -m "Trigger Build"
[main fa8acc7] Trigger Build
➜ kubernetes-example (main) ✔ git push origin main

在这里插入图片描述
可以看到 Pipeline 包含 3 个 Task 及其输出的日志信息。
在这里插入图片描述

kubectl get pods |grep github
github-run-n964p-build-and-push-backend-pod            2/2     Running     0               3m10s
github-run-n964p-build-and-push-frontend-pod           2/2     Running     0               3m10s
github-run-n964p-clone-pod                             0/1     Completed   0               3m36s

使用 Harbor 搭建企业级镜像仓库

前提:k8s环境中已安装好helm3(https://helm.sh/docs/intro/install/)

在 Tekton Pipeline 中使用 Harbor

要在 Tekton Pipeline 中使用 Harbor,需要将 Pipeline 中的spec.params.registry_url变量值由 docker.io 修改为 harbor.n7t.dev,并且将spec.params.registry_mirror变量值修改为 library。可以使用 kubectl edit 命令来修改。

$ kubectl edit Pipeline github-trigger-pipeline
...
  params:
  - default: harbor.n7t.dev  # 修改为 harbor.n7t.dev(域名使用自己的)
    name: registry_url
    type: string
  - default: "library"  # 修改为 library
    name: registry_mirror
    type: string
...

然后再修改镜像仓库的凭据,也就是 registry-auth Secret。

$ kubectl edit secret registry-auth
apiVersion: v1
data:
  password: SGFyYm9yMTIzNDUK   # 修改为 Base64 编码:Harbor12345
  username: YWRtaW4K           # 修改为 Base64 编码:admin
kind: Secret

注:生产环境中请修改默认密码!!!

回到本地示例应用 kubernetes-example 目录,向仓库推送一个空的 commit 来触发 Tekton 流水线。

访问Tekton dashboard页面 查看流水线运行状态,运行结束后,登录Harbor仓库中检查有咩有刚才 Tekton 推送的新镜像。

附:

Harbor 生产建议:

  1. 确认 PVC 是否支持在线扩容。
  2. 尽量使用 S3 作为镜像存储系统。
  3. 使用外部数据库和 Redis。
  4. 开启自动镜像扫描和阻止漏洞镜像。

参考资料:
https://time.geekbang.org/column/article/623839
https://www.lixueduan.com/posts/tekton/01-deploy-tekton/#

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

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

相关文章

markdown2html 转化流程

定义一个extensions function markedMention() {return {extensions: [{name: mention,level: inline,start(src) {// console.log("markedMention start....", src);return src.indexOf(#)},tokenizer(src, tokens) {const rule /^(#[a-zA-Z0-9])\s?/const match…

巴斯夫与长三角物理研究中心开展合作,专注固态和钠离子电池领域

“巴斯夫,全球知名化学公司,宣布与长三角物理研究中心合作,在江苏溧阳市成立联合研究中心,专注于固态电池和钠离子电池的科研。” 根据巴斯夫官方微博消息,新成立的研究中心名为“巴斯夫–长三角物理研究中心新能源汽车…

RAID6故障导致分区打不开的服务器数据恢复案例

服务器数据恢复环境: 一台infortrend存储,有一组由12块硬盘组建的RAID6,RAID6的所有空间划分给一个LUN并映射到WINDOWS系统上,WINDOWS系统上划分了一个GPT分区。 服务器故障&分析: 存储无法访问,经过检…

TIOBE统计数据

TIOBE统计数据(2023年7月) TIOBE Index编程社区指数是编程语言流行度的一个指标。评级基于全球熟练工程师的数量、课程和第三方供应商的数量。Google、Bing、Yahoo!、维基百科、亚马逊、YouTube 和百度等流行搜索引擎用于计算评级。 七月头条&#xff1…

【C语言提升】深入了解动态内存管理

目录 一、静态分配和动态分配 二、内存管理函数 1、malloc 申请堆区空间 2、calloc 申请堆区空间 3、free回收堆区空间权限 4、memset内存设置函数 5、realloc内存增减函数 三、内存泄漏(了解) 一、静态分配和动态分配 1、静态分配 在程序编译…

【Python】类型注解 ② ( 基础变量设置类型注解 | 类对象设置类型注解 | 容器变量设置简易类型注解 | 容器变量设置详细类型注解 )

文章目录 一、为变量设置类型类型注解1、变量设置 " 类型注解 " 语法2、为 基础类型变量 设置 " 类型注解 "3、为 类 的 对象类型 设置 " 类型注解 "4、为 基础容器类型变量 设置 简易 " 类型注解 "5、为 基础容器类型变量 设置 详细 …

gma 2 教程(二)数据操作:3. 支持生成的栅格格式信息

为了方便了解和选择输出栅格格式、配置高级创建选项,下表列出了gma可以生成(复制/创建/转换)的所有栅格格式的主要信息: 格式名生成模式支持数据类型扩展名多维栅格支持色彩映射表支持的数据类型多波段支持压缩模式AAIGrid复制By…

Redis学习(三)分布式缓存、多级缓存、Redis实战经验、Redis底层原理

文章目录 分布式缓存Redis持久化RDB持久化AOF持久化 Redis主从Redis数据同步原理全量同步增量同步 Redis哨兵哨兵的作用和原理sentinel(哨兵)的三个作用是什么?sentinel如何判断一个Redis实例是否健康?master出现故障后&#xff0…

Java-API简析_java.lang.ProcessBuilder类(基于 Latest JDK)(浅析源码)

【版权声明】未经博主同意,谢绝转载!(请尊重原创,博主保留追究权) https://blog.csdn.net/m0_69908381/article/details/131729933 出自【进步*于辰的博客】 因为我发现目前,我对Java-API的学习意识比较薄弱…

echarts_柱状图+漏斗图

目录 柱状图(bar)需求[1] 复制案例[2] 修改类目轴方向[3] 修改数据渲染方向[4] 修改坐标轴文本样式 漏斗图(funnel)漏斗图的形状 柱状图(bar) 需求 如上图,做一个横向柱状图,后端返回的数据是从小向大排列的数据,希望能够按照顺序进行展示。…

pnpm安装方式

pnpm安装方式 要使用pnpm进行安装,首先需要确保已经安装了Node.js。然后,按照以下步骤进行pnpm的安装: 打开终端或命令提示符。 在命令行中输入以下命令来全局安装pnpm: npm install -g pnpm这将使用npm将pnpm包全局安装到您的…

WireShark

文章目录 IP协议部分协议对应协议号路由器IP分片IP分片的缺点 TCP协议[TCP MSS](https://blog.csdn.net/meihualing/article/details/113739693) UDP协议ARP ICMPDHCPDNSFTP wireshark可以学习网络协议,解决一些问题 IP协议 IP指网际互连协议,Internet P…

动态规划01背包之1049 最后一块石头的重量 II(第9道)

题目: 有一堆石头,用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。 每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 。那么粉碎的可能结果如下: …

Verilog 学习之路

循环 7-10 代码段 generategenvar i;for (i0; i<8; i i1) begin: my_block_nameassign out[i] in[8-i-1];end endgenerate解释 该代码使用了 S y s t e m V e r i l o g SystemVerilog SystemVerilog 中的 g e n e r a t e generate generate 构造&#xff0c;它允许在…

【Docker】快速入门,带你快速了解 Docker

文章底部有投票活动&#xff0c;赶快参与进来吧&#x1f603; 相信大家在开发过程中都听说过 Docker 一词&#xff0c;至于 Docker 在开发中扮演的角色&#xff0c;估计好多人都说不上来&#xff0c;今天就让阿Q带大家一起揭开它神秘的面纱&#xff01; 文章目录 什么是容器&a…

【C++初阶】C++入门——内联函数、auto、范围for、nullptr

文章目录 一、内联函数1.1 定义1.2 特性 二、auto关键字2.1 简介2.2 auto使用细则2.3 不能使用auto的场景 三、基于范围的for循环3.1 范围for的使用条件 四、指针空值nullptr 一、内联函数 普通的函数在调用的时候会开辟函数栈帧&#xff0c;会产生一定量的消耗&#xff0c;在C…

《算法竞赛·快冲300题》每日一题:“推箱子”

《算法竞赛快冲300题》将于2024年出版&#xff0c;是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码&#xff0c;以中低档题为主&#xff0c;适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 推…

1 考试宝自建题库使用说明

注意&#xff1a; 标准格式&#xff1a;括号里不写对象&#xff0c;然后答案行数另取一行&#xff0c;放在选项后一行也是可以的&#xff0c;选项可以横排或者竖排。横排的话选项要用空格隔开&#xff0c;选项的ABCD要加"."&#xff0c;如A. B. C. D. 1. 法治中国…

多个电源模块带电感,给一个负载用的直流压降仿真-CORE电源

多个电源模块带电感,给一个负载用的直流压降仿真-CORE电源 下面介绍如何对多个电源模块带电感,给一个负载用的直流压降仿真,常见于CPU的CORE电源。以下图为例 具体操作步骤如下 设置VRAM(因为是多个电源输出,所以每个电源都要设置成VRAM)

【C语言】轻松模拟实现qsort函数

君兮_的个人主页 勤时当勉励 岁月不待人 C/C 游戏开发 Hello,米娜桑们&#xff0c;这里是君兮_&#xff0c;我们今天接着上回更新的内容&#xff0c;讲讲我们如何模拟实现自己的qsort函数&#xff0c; 废话不多说&#xff0c;我们开始今天的内容。 模拟实现qsort函数 qsort函…