云原生的 CI/CD 框架tekton - pipeline(一)

文章目录

    • 1. 官方介绍
    • 2. 组件
      • 2.1 Tekton Pipelines
      • 2.2 部署pipeline
      • 2.3 部署dashborad
        • 2.3.1 task
        • 2.3.2 taskrun
        • 2.3.3 Pipeline
        • 2.3.4 PipelineRun
    • 3. 案例
      • 案例1: 拉取代码并查看readme
        • step1: 创建task - 拉取代码
        • step2: 创建task - 查看reamde
        • step3: 创建task的编排 - pipeline
        • step4: 创建secrets - ssh key/username
        • step5: 创建serviceaccount
        • step6: 创建pipelinerun
      • 案例2:构建和推送镜像
        • step1: 创建task - 拉取代码
        • step2: 创建task - 构建代码
        • step3: 创建task - 打包镜像
        • step4: 创建secret - docker 认证
        • step5: 创建serviceaccount
        • step6: 创建task编排 - pipeline
        • step7: 创建pipelinerun

1. 官方介绍

Tekton 的前身是 Knative 项目的 build-pipeline 项目,这个项目是为了给 build 模块增加 pipeline 的功能,但是随着不同的功能加入到 Knative build 模块中,build 模块越来越变得像一个通用的 CI/CD 系统,于是,索性将 build-pipeline 剥离出 Knative,就变成了现在的 Tekton,而 Tekton 也从此致力于提供全功能、标准化的云原生 CI/CD 解决方案。

Tekton 是一个功能强大且灵活的 Kubernetes 原生开源框架,用于创建持续集成和交付(CI/CD)系统。通过抽象底层实现细节,用户可以跨多云平台和本地系统进行构建、测试和部署。

一句话总结:Tekton 是云原生的 CI/CD 框架,是云原生的的 CI/CD 解决方案

2. 组件

Tekton 由一些列组件组成:

  • Tekton Pipelines:是 Tekton 的基础,它定义了一组 Kubernetes CRD 作为构建块,我们可以使用这些对象来组装 CI/CD 流水线。
  • Tekton Triggers:允许我们根据事件来实例化流水线,例如,可以我们在每次将 PR/MR 合并到 GitHub/GitLab 仓库的时候触发流水线实例和构建工作。
  • Tekton CLI:提供了一个名为 tkn的命令行界面,它构建在 Kubernetes CLI 之上,运行和 Tekton 进行交互。
  • Tekton Dashboard:是 Tekton Pipelines的基于 Web 的一个图形界面,可以线上有关流水线执行的相关信息。
  • Tekton Catalog:是一个由社区贡献的高质量 Tekton 构建块(任务、流水线等)存储库,可以直接在我们自己的流水线中使用这些构建块。用于访问 Tekton Catalog的 Web 图形界面工具叫Tekton Hub
  • Tekton Operator:是一个 Kubernetes Operator,可以让我们在 Kubernetes 集群上安装、更新、删除 Tekton 项目。

2.1 Tekton Pipelines

参考链接:https://tekton.dev/docs/concepts/concept-model/

Tekton Pipeline中有5类对象,核心理念是通过定义yaml定义构建过程。

  • task:task表示一个任务,task里可以定义一系列的steps,例如编译代码、构建镜像、推送镜像等,每个step实际由一个Pod执行。
  • taskRun:task只是定义了一个模版,taskRun才真正代表了一次实际的运行,当然你也可以自己手动创建一个taskRun,taskRun创建出来之后,就会自动触发task描述的构建任务。
  • PipelineResource:表示pipeline input资源,比如github上的源码,或者pipeline output资源,例如一个容器镜像或者构建生成的jar包等,目前已经弃用。
  • Pipeline:一个或多个task、PipelineResource以及各种定义参数的集合。
  • PipelineRun:类似task和taskRun的关系,pipelineRun也表示某一次实际运行的pipeline,下发一个pipelineRun CRD实例到kubernetes后,同样也会触发一次pipeline的构建。

2.2 部署pipeline

# install
kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
# moinitor
kubectl get pods --namespace tekton-pipelines --watch

2.3 部署dashborad

# install
kubectl apply --filename https://storage.googleapis.com/tekton-releases/dashboard/latest/release-full.yaml
# monitor
kubectl port-forward -n tekton-pipelines service/tekton-dashboard 9097:9097
# expose port
kubectl port-forward -n tekton-pipelines service/tekton-dashboard 9097:9097

pipeline和task的关系
在这里插入图片描述
pipeline和pipelinerun的关系
在这里插入图片描述

2.3.1 task

Task 就是一个任务执行模板,之所以说 Task 是一个模板是因为 task 定义中可以包含变量,Task 在真正执行的时候需要给定变量的具体值。

如果把 Tekton 的 Task 有点儿类似于定义一个函数,Task 通过 inputs.params 定义需要哪些入参,并且每一个入参还可以指定默认值。Task 的 steps 字段表示当前 task 是有哪些步骤组成的,每一个步骤具体就是基于镜像启动一个 container 执行一些操作,container 的启动参数可以通过 task 的入参使用模板语法进行配置。

Demo1:test-task.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: test
spec:
  params:
  - name: username
    type: string
    default: "hello,cs"
  steps:
    - name: echo
      image: alpine
      script: |
        #!/bin/sh
        echo "$(params.username)"

Demo2:task-git.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: clone-code-test
  description: This Task will clone code and search file
spec:
  steps:
    - name: clone-code-test
      image: alpine/git
      script: |
        #!/bin/sh
        echo "Hello World"
        git clone https://gitlab.com/kaixuan.wang/app.git
        cd app
        cat README.md

也可以对demo2进行调整如下:

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: clone-code-test
  description: This Task will clone code and search file
spec:
  params:
  - name: repo-url
    type: string
    default: "https://gitlab.com/kaixuan.wang/gitops.git"
  steps:
    - name: clone-code-test
      image: alpine/git
      script: |
        #!/bin/sh
        echo "Hello World"
        git clone $(params.repo-url)
        ls -l gitops
#  params:
#    - name: repo-url
#      value: git@jihulab.com:cs-test-group1/kxwang/test.git
2.3.2 taskrun

Task 定义好以后是不能执行的,就像一个函数定义好以后需要调用才能执行一样。所以需要再定义一个 TaskRun 去执行 Task。

TaskRun 主要是负责设置 Task 需要的参数,并通过 taskRef 字段引用要执行的 Task。

Demo1:

test-task-run.yaml(赋值username)

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  name: test-task-run #taskrun name
spec:
  taskRef:
    name: test
  params:
  - name: username
    value: "Tekton"

test-task-2.yaml(不赋值)

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  name: test-task-run-1 #taskrun name
spec:
  taskRef:
    name: test

通过tkn工具查看
在这里插入图片描述
然而在实际使用过程中,我们一般很少使用TaskRun,因为它只能给一个Task 传参,Tekton提供了给多个Task同时传参的解决方案Pipeline和PipelineRun。

Demo2:taskrun-git.yaml

apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  generateName: taskrun-git-  # name: taskrun-git
spec:
  taskRef:
    name: clone-code
apiVersion: tekton.dev/v1beta1
kind: TaskRun
metadata:
  generateName: taskrun-git-
spec:
  taskRef:
    name: clone-code
#  params:
#  - name: repo-url
#    value: "https://gitlab.com/test-ce/group/123.git"
2.3.3 Pipeline

一个 TaskRun 只能执行一个 Task,当需要编排多个 Task 的时候就需要用到 Pipeline。

Pipeline 是一个编排 Task 的模板。

  • Pipeline 的 params 声明了执行时需要的入参。
  • Pipeline 的 spec.tasks 定义了需要编排的 Task。
  • Tasks 是一个数组,数组中的 task 并不是通过数组声明的顺序去执行的,而是通过 runAfter 来声明 task 执行的顺序。

Tekton controller 在解析 CRD 的时候会解析 Task 的顺序,然后根据 runAfter 设置生成的依次树依次去执行。Pipeline 在编排 Task 的时候需要给每一个 Task 传入必须的参数,这些参数的值可以来自 Pipeline 自身的 params 设置。下面是一个Demo:

pipeline.yaml

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: test-pipeline
spec:
  params:
  - name: username
    type: string
  tasks:
    - name: test-1
      taskRef:
        name: test
      params:
      - name: username
        value: $(params.username)
#    - name: clone-code-test
#      runAfter:
#        - test-1
#      taskRef:
#        name: clone-code-test
2.3.4 PipelineRun

和 Task 一样 Pipeline 定义完成以后也是不能直接执行的,需要 PipelineRun 才能执行 Pipeline。PipelineRun 的主要作用是给 Pipeline 传入必要的入参,并执行 Pipeline。

pipelinerun.yaml

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: test-pipeline-run-
spec:
  pipelineRef:
    name: test-pipeline
  params:
  - name: username
    value: "Tekton"

3. 案例

案例1: 拉取代码并查看readme

step1: 创建task - 拉取代码

安装git-clone task

kubectl apply -f https://raw.githubusercontent.com/tektoncd/catalog/main/task/git-clone/0.9/git-clone.yaml

或者自己创建一个git-clone task

cat task.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
 name: git-clone
spec:
 workspaces:
   - name: output
   - name: ssh-directory
 params:
   - name: url
     type: string
   - name: revision
     type: string
     default: ""
 steps:
   - name: clone
     image: "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.40.2"
     env:
       - name: PARAM_URL
         value: $(params.url)
       - name: PARAM_REVISION
         value: $(params.revision)
       - name: WORKSPACE_OUTPUT_PATH
         value: $(workspaces.output.path)
       - name: WORKSPACE_SSH_PATH
         value: $(workspaces.ssh-directory.path)
     script: |
      #!/usr/bin/env sh
       mkdir $HOME/.ssh
       cp $WORKSPACE_SSH_PATH/* $HOME/.ssh/
       chmod 400 $HOME/.ssh/*
       set -eu
       CHECKOUT_DIR="${WORKSPACE_OUTPUT_PATH}"
       /ko-app/git-init \
         -url="${PARAM_URL}" \
         -revision="${PARAM_REVISION}" \
         -path="${CHECKOUT_DIR}"
       cd "${CHECKOUT_DIR}"
       EXIT_CODE="$?"
       if [ "${EXIT_CODE}" != 0 ] ; then
         exit "${EXIT_CODE}"
       fi
step2: 创建task - 查看reamde

cat show-readme.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: show-readme
spec:
  workspaces:
  - name: source
  steps:
  - name: show-readme
    image: alpine:latest
    script: |
      cat $(workspaces.source.path)/README.md
step3: 创建task的编排 - pipeline

cat pipeline.yaml

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
 name: cat-branch-readme
spec:
 params:
   - name: repo-url
     type: string
   - name: branch-name
     type: string
 workspaces:
   - name: shared-data
   - name: git-credentials
 tasks:
   - name: fetch-repo
     taskRef:
       name: git-clone
     workspaces:
       - name: output
         workspace: shared-data
       - name: ssh-directory
         workspace: git-credentials
     params:
       - name: url
         value: $(params.repo-url)
       - name: revision
         value: $(params.branch-name)
   - name: show-readme
     runAfter: ["fetch-repo"]
     taskRef:
       name: show-readme
     workspaces:
       - name: source
         workspace: shared-data
step4: 创建secrets - ssh key/username

secrets-ssh.yaml

apiVersion: v1
kind: Secret
metadata:
    name: gitlab-ssh
    annotations:
      tekton.dev/git-0: jihulab.com #不需要指定协议,如果带http://或者https://会报错
type: kubernetes.io/ssh-auth
data:
    ssh-privatekey: <cat ~/.ssh/id_rsa | base64 -w0>
    known_hosts: <cat ~/.ssh/known_hosts | base64 -w0>

创建secrets - username

secrets-basic.yaml

apiVersion: v1
kind: Secret
metadata:
  name: gitlab-auth
  annotations:
    tekton.dev/git-0: https://jihulab.com #需要指定协议,如果不带会报错
type: kubernetes.io/basic-auth
stringData:
  username: kxwang@jihulab.com
  password: xxxxxxx
step5: 创建serviceaccount

gitlab-sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-sa
secrets:
- name: gitlab-auth
- name: gitlab-ssh
step6: 创建pipelinerun

cat pipelinerun.yaml

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: git-clone-checking-out-a-branch
spec:
  serviceAccountName: gitlab-sa
  pipelineRef:
    name: cat-branch-readme
  podTemplate:
    securityContext:
      fsGroup: 65532
  workspaces:
    - name: shared-data
      volumeClaimTemplate:
        spec:
          accessModes:
            - ReadWriteOnce
          resources:
            requests:
              storage: 256Mi
          volumeMode: Filesystem
    - name: git-credentials
      secret:
        secretName: gitlab-ssh
  params:
    - name: repo-url
      value: git@jihulab.com:cs-test-group1/kxwang/test.git
    - name: branch-name
      value: master

案例2:构建和推送镜像

step1: 创建task - 拉取代码

同上

step2: 创建task - 构建代码

task-build.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: build-1
spec:
  workspaces:
    - name: source # 名称
  params:
   - name: skipunit
     type: string
     default: "true"
  steps:
  - name: build
    image: maven:3-jdk-8
    workingDir: $(workspaces.source.path)
    script: |
      #/usr/bin/env sh
      mvn clean package -Dmaven.test.skip=$(params.skipunit)
    volumeMounts:
      - name: cache
        mountPath: /workspace/.m2
        subPath: m2-cache
      - name: cache
        mountPath: /workspace/.cache
        subPath: m2-cache
  volumes:
    - name: cache
      emptyDir: {}
step3: 创建task - 打包镜像

task-package.yaml

apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: package-1
spec:
  workspaces:
    - name: source # 名称
  params:
   - name: image_dest
     type: string
   - name: image_tag
     type: string
     default: "latest"
   - name: DockerfilePath
     type: string
     default: Dockerfile
   - name: Context
     type: string
     default: .
  steps:
  - name: package
    image: docker:stable
    workingDir: $(workspaces.source.path)
    script: |
      #/usr/bin/env sh
      docker login registry.ap-southeast-1.aliyuncs.com
      docker build -t $(params.image_dest):$(params.image_tag) -f $(params.DockerfilePath) $(params.Context)
      docker push $(params.image_dest):$(params.image_tag)
    volumeMounts:
      - name: dockersorck
        mountPath: /var/run/docker.sock
  volumes:
    - name: dockersorck
      hostPath:
        path: /var/run/docker.sock
step4: 创建secret - docker 认证

1、config.json(~/.docker/config.json)

{
	"auths": {
		"registry.ap-southeast-1.aliyuncs.com": {
			"auth": "d2t4XzA0MjJAMTYzLmNvbTp3a3g3MzE1MDg4MDY="
		}
	}
}

2、secret-docker.yaml

apiVersion: v1
kind: Secret
metadata:
  name: docker-credentials
  annotations:
    tekton.dev/docker-0: https://registry.ap-southeast-1.aliyuncs.com
type: kubernetes.io/basic-auth
stringData:
  username: wkx_0422@163.com
  password: 123456
step5: 创建serviceaccount

gitlab-sa.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: gitlab-sa
secrets:
- name: gitlab-auth
- name: gitlab-ssh
- name: docker-credentials
step6: 创建task编排 - pipeline

pipeline.yaml

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: clone-build-push-1
spec:
  description: |
    This pipeline clones a git repo, builds a Docker image with Kaniko and
    pushes it to a registry
  params:
  - name: repo-url
    type: string
  - name: image_dest
    type: string
  - name: image_tag
    type: string
  workspaces:
  - name: shared-data
  tasks:
  # 拉取代码
  - name: fetch-source
    taskRef:
      name: git-clone
    workspaces:
    - name: output
      workspace: shared-data
    params:
    - name: url
      value: $(params.repo-url)
  # 打包
  - name: build-code
    taskRef:
      name: build-1
    workspaces:
    - name: source
      workspace: shared-data
    runAfter:
      - fetch-source
  # 构建并推送镜像
  - name: package-image
    runAfter: ["build-code"]
    taskRef:
      name: package-1
    workspaces:
    - name: source
      workspace: shared-data
    params:
    - name: image_dest
      value: $(params.image_dest)
    - name: image_tag
      value: $(params.image_tag)
step7: 创建pipelinerun

pipelinerun.yaml

apiVersion: tekton.dev/v1beta1
kind: PipelineRun
metadata:
  generateName: clone-build-push-run-
spec:
  serviceAccountName: gitlab-sa
  pipelineRef:
    name: clone-build-push-1
  podTemplate:
    securityContext:
      fsGroup: 65532
  workspaces:
  - name: shared-data
    volumeClaimTemplate:
      spec:
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 128Mi
  params:
  - name: repo-url
    value: https://jihulab.com/cs-test-group1/kxwang/test.git
  - name: image_dest
    value: registry.ap-southeast-1.aliyuncs.com/my_image_repo/demo
  - name: image_tag
    value: v2

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

深入理解CyclicBarrier

文章目录 1. 概念2. CylicBarier使用简单案例3. 源码 1. 概念 CyclicBarrier 字面意思回环栅栏&#xff08;循环屏障&#xff09;&#xff0c;通过它可以实现让一组线程等待至某个状态&#xff08;屏障点&#xff09;之后再全部同时执行。叫做回环是因为当所有等待线程都被释放…

智能优化算法应用:基于法医调查算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于法医调查算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于法医调查算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.法医调查算法4.实验参数设定5.算法结果6.参考…

Unity 状态系统

状态系统 原理食用方法Demo 原理 #mermaid-svg-lUbxJ8eMP3KqrEhY {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-lUbxJ8eMP3KqrEhY .error-icon{fill:#552222;}#mermaid-svg-lUbxJ8eMP3KqrEhY .error-text{fill:#55…

使用RSA工具进行对信息加解密

我们在开发中需要对用户敏感数据进行加解密&#xff0c;比如密码 这边科普一下RSA算法 RSA是非对称加密算法&#xff0c;与对称加密算法不同;在对称加密中&#xff0c;相同的密钥用于加密和解密数据,因此密钥的安全性至关重要;而在RSA非对称加密中&#xff0c;有两个密钥&…

一文说清google最新大模型Gemini

随着AI技术的快速发展&#xff0c;谷歌和其他科技巨头在研究和部署上的竞争也越来越激烈。本月12月6号谷歌CEO哈萨比斯在谷歌官网发文&#xff0c;宣布推出万众瞩目的多模态大模型Gemini。标题明晃晃写着“最大”、“最强”&#xff0c;主打的就是一个干爆GPT-4。 一、Gemini的…

unity 2d 入门 飞翔小鸟 场景延续(八)

1、新建c#脚本如下 代码&#xff0c;在前方生成生成自身图片并3s后销毁自身&#xff0c;在碰撞物体后小鸟死亡后不删除自身 using System.Collections; using System.Collections.Generic; using UnityEngine;public class CopyScene : MonoBehaviour { //要复制的对象public…

银行卡二要素API的应用案例:从在线购物到金融投资

引言 随着互联网技术的不断发展&#xff0c;人们的金融需求也在不断增加。随之而来的是各种新型金融服务的涌现&#xff0c;让用户的金融体验更加便利快捷。其中&#xff0c;银行卡二要素API的应用&#xff0c;则为用户的金融体验和安全性提供了极大的保障。 银行卡二要素API…

计算机存储单位 + 程序编译过程

C语言的编译过程 计算机存储单位 头文件包含的两种方式 使用 C/C 程序常用的IDE 常用的C语言编译器&#xff1a; 在选择编译器时&#xff0c;需考虑平台兼容性、性能优化、调试工具和开发人员的个人偏好等因素。 详细教程可转 爱编程的大丙

Python---random库

目录 基本随机数函数(): rand.seed() random() 扩展随机数函数(): random库包含两类函数&#xff1a;基本随机数函数&#xff0c;扩展随机数函数 基本随机数函数:seed(),random() 扩展随机数函数&#xff1a;randint,getrandbits(),uniform(),randrange(),choice(),shuff…

JumpServer初探

JumpServer资产&#xff0c;用户关系如图所示。 资产管理下有资产列表和系统用户&#xff0c;系统用户分为特权用户和普通用户。资产列表下管理的是服务器&#xff0c;而特权用户就是JumpServer用来登录服务器的账号&#xff0c;因此特权用户需要拥有较高的权限&#xff0c;比…

AWS攻略——Peering连接VPC

文章目录 创建IP/CIDR不覆盖的VPC创建VPC创建子网创建密钥对创建EC2 创建Peering接受Peering邀请修改各个VPC的路由表修改美东us-east-1 pulic subnet的路由修改悉尼ap-southeast-2路由 测试知识点 我们回顾下《AWS攻略——VPC初识》中的知识&#xff1a; 一个VPC只能设置在一…

五、HotSpot细节实现

一、并发标记与三色标记 问题&#xff1a;三色标记到底发生在什么阶段&#xff0c;替代了什么。并发标记 1、并发标记( Concurrent Marking) 从 GC Root 开始对堆中对象进行可达性分析&#xff0c;递归扫描整个堆里的对象图&#xff0c;找出要回收的对象&#xff0c;这阶段耗…

Vue学习计划-Vue2--VueCLi(二)vuecli脚手架创建的项目内部主要文件分析

1. 文件分析 1. 补充&#xff1a; 什么叫单文件组件&#xff1f; 一个文件中只有一个组件 vue-cli创建的项目中&#xff0c;.vue的文件都是单文件组件&#xff0c;例如App.vue 2. 进入分析 1. package.json: 项目依赖配置文件&#xff1a; 如图&#xff0c;我们说主要的属性…

C++学习之路(十九)C++ 用Qt5实现一个工具箱(用SQLite数据库来管理粘贴板数据)- 示例代码拆分讲解

上篇文章&#xff0c;我们用 Qt5 实现了在小工具箱中添加了《点击按钮以新窗口打开功能面板》功能。今天我们把粘贴板功能用SQLite数据库来管理&#xff0c;用SQLite来实现增删改查。下面我们就来看看如何来规划开发这样的小功能并且添加到我们的工具箱中吧。 老规矩&#xff…

实现:切换页面切换标题,扩展 vue-router 的类型

布局容器-页面标题 网址&#xff1a;https://router.vuejs.org/zh/guide/advanced/meta 给每一个路由添加 元信息 数据 router/index.ts const router createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{ path: /login, component: () > im…

LeetCode(52)最小栈【栈】【中等】

目录 1.题目2.答案3.提交结果截图 链接&#xff1a; 最小栈 1.题目 设计一个支持 push &#xff0c;pop &#xff0c;top 操作&#xff0c;并能在常数时间内检索到最小元素的栈。 实现 MinStack 类: MinStack() 初始化堆栈对象。void push(int val) 将元素val推入堆栈。void…

PandoraFMS 监控软件 任意文件上传漏洞复现

0x01 产品简介 Pandora FMS 是用于监控计算机网络的软件。 Pandora FMS 允许以可视化方式监控来自不同操作系统、服务器、应用程序和硬件系统(例如防火墙、代理、数据库、Web 服务器或路由器)的多个参数的状态和性能。 0x02 漏洞概述 PandoraFMS upload_head_image.php 接…

web前端开发html/css练习

目标图&#xff1a; 素材&#xff1a; 代码&#xff1a; <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"…

通过误差改变控制的两种策略

如果反馈误差越来越大&#xff0c;需要改变调节方向以减小误差并实现更好的控制。以下是两种常见的调节方向改变的方法&#xff1a; PID控制器中的积分限制&#xff1a;在PID控制中&#xff0c;积分项可以用来减小稳态误差。然而&#xff0c;当反馈误差持续增大时&#xff0c;积…

8、操作符重载

友元 可以通过friend关键字&#xff0c;把一个全局函数、另一个类的成员函数或者另一个类整体&#xff0c;声明为授权类的友元友元拥有访问授权类任何非公有成员的特权友元声明可以出现在授权类的公有、私有或者保护等任何区域且不受访问控制限定符的约束友元不是成员&#xf…