k8s上搭建devops环境

一、gitlab

1.安装gitlab

# 下载安装包
wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el7/gitlab-ce-15.9.1-ce.0.el7.x86_64.rpm

# 安装
rpm -i gitlab-ce-15.9.1-ce.0.el7.x86_64.rpm


# 编辑 vi /etc/gitlab/gitlab.rb 文件
# 修改 external_url 访问路径 http://192.168.50.76:28080/
# 其他配置修改如下
gitlab_rails['time_zone'] = 'Asia/Shanghai'
puma['worker_processes'] = 2
sidekiq['max_concurrency'] = 8
postgresql['shared_buffers'] = "128MB"
postgresql['max_worker_processes'] = 4
prometheus_monitoring['enable'] = false

# 更新配置并重启
gitlab-ctl reconfigure
gitlab-ctl restart

2.页面配置

# 查看默认密码
cat /etc/gitlab/initial_root_password

访问url http://192.168.50.76:28080/   

root/TkT5HbRv/zkPl8mh1lFZMrDzlat9n3eVM7CYJQyHaNk=
# 登录后修改默认密码 > 右上角头像 > Perferences > Password

# 修改系统配置:点击左上角三横 > Admin
# Settings > General > Account and limit > 取消 Gravatar enabled > Save changes

# 关闭用户注册功能
# Settings > General > Sign-up restrictions > 取消 Sign-up enabled > Save changes

# 开启 webhook 外部访问
# Settings > Network > Outbound requests > Allow requests to the local network from web hooks and services 勾选

# 设置语言为中文(全局)
# Settings > Preferences > Localization > Default language > 选择简体中文 > Save changes

# 设置当前用户语言为中文
# 右上角用户头像 > Preferences > Localization > Language > 选择简体中文 > Save changes

3.配置Secret

# 创建 gitlab 默认用户名密码 secret
echo root > ./username
echo wolfcode > password


kubectl create secret generic git-user-pass --from-file=./username --from-file=./password -n kube-devops

4.为项目配置webhook

进入项目点击侧边栏设置 > Webhooks 进入配置即可

URL:在 jenkins 创建 pipeline 项目后
触发来源:
推送事件:表示收到新的推送代码就会触发
标签推送事件:新标签推送才会触发
评论:根据评论决定触发
合并请求事件:创建、更新或合并请求触发

添加成功后,可以在下方点击测试按钮查看 jenkins 是否成功触发构建操作

5.卸载

# 停止服务
gitlab-ctl stop

# 卸载 rpm 软件(注意安装的软件版本是 ce 还是 ee)
rpm -e gitlab-ce

# 查看进程
ps -ef|grep gitlab 
# 干掉第一个 runsvdir -P /opt/gitlab/service log 进程

# 删除 gitlab 残余文件
find / -name *gitlab* | xargs rm -rf
find / -name gitlab | xargs rm -rf

二、harbor

0.安装docker-compose

注意docker跟docker-compose版本对应关系

我们这里docker是26.1.4

#下载

wget https://github.com/docker/compose/releases/download/v2.27.0/docker-compose-linux-x86_64

#移动到/usr/local/bin下

mv docker-compose-linux-x86_64 /usr/local/bin/docker-compose

#赋予执行权限

chmod +x /usr/local/bin/docker-compose

测试是否安装成功

docker-compose --version

1.安装harbor

# 下载 harbor 安装包
wget https://github.com/goharbor/harbor/releases/download/v2.5.0/harbor-offline-installer-v2.5.0.tgz
# 解压

tar -zxvf harbor-v2.5.0.tar.gz

#修改配置 

cp harbor.yml.tmpl harbor.yml

vi harbor.yml

执行 sh  install.sh 就行

查看是否启动成功

docker-compose ls

docker ps -a | grep harbor

访问url:  192.168.50.76:8858  admin/wolfcode

2.配置Secret

# 创建 harbor 访问账号密码(需要将下访问的配置信息改成你自己的)
kubectl create secret docker-registry harbor-secret --docker-server=192.168.50.76:8858 --docker-username=admin --docker-password=wolfcode -n kube-devops

查看是否创建完成

kubectl get secret -n kube-devops

3.配置docker(集群中每个节点)

vi /etc/docker/daemon.json

加入"insecure-registries":["192.168.50.76:8858"]

systemctl daemon-reload

systemctl restart docker

4.验证是否生效

docker login -uadmin 192.168.50.76:8858

三、SonarQube

1.安装

我安装的最新的sonarqube是sonarqube:9.9-community,注意sonarqube和jdk、sonar-maven-plugin有版本匹配问题。

# 进入 /opt/k8s/devops

pgsql.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-data
  namespace: kube-devops
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "managed-nfs-storage"
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres-sonar
  namespace: kube-devops
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres-sonar
  template:
    metadata:
      labels:
        app: postgres-sonar
    spec:
      containers:
      - name: postgres-sonar
        image: postgres:14.2
        ports:
        - containerPort: 5432
        env:
        - name: POSTGRES_DB
          value: "sonarDB"
        - name: POSTGRES_USER
          value: "sonarUser"
        - name: POSTGRES_PASSWORD 
          value: "123456"
        volumeMounts:
          - name: data
            mountPath: /var/lib/postgresql/data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: postgres-data
---
apiVersion: v1
kind: Service
metadata:
  name: postgres-sonar
  namespace: kube-devops
  labels:
    app: postgres-sonar
spec:
  type: NodePort
  ports:
  - name: postgres-sonar
    port: 5432
    targetPort: 5432
    protocol: TCP
  selector:
    app: postgres-sonar

sonarqube.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sonarqube-data
  namespace: kube-devops
spec:
  accessModes:
    - ReadWriteMany
  storageClassName: "managed-nfs-storage"
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sonarqube
  namespace: kube-devops
  labels:
    app: sonarqube
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sonarqube
  template:
    metadata:
      labels:
        app: sonarqube
    spec:
      initContainers:
      - name: init-sysctl
        image: busybox:1.28.4
        command: ["sysctl", "-w", "vm.max_map_count=262144"]
        securityContext:
          privileged: true
      containers:
      - name: sonarqube
        image: sonarqube:9.9-community
        ports:
        - containerPort: 9000
        env:
        - name: SONARQUBE_JDBC_USERNAME
          value: "sonarUser"
        - name: SONARQUBE_JDBC_PASSWORD
          value: "123456"
        - name: SONARQUBE_JDBC_URL
          value: "jdbc:postgresql://postgres-sonar:5432/sonarDB"
        livenessProbe:
          httpGet:
            path: /sessions/new
            port: 9000
          initialDelaySeconds: 60
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /sessions/new
            port: 9000
          initialDelaySeconds: 60
          periodSeconds: 30
          failureThreshold: 6
        volumeMounts:
        - mountPath: /opt/sonarqube/conf
          name: data
        - mountPath: /opt/sonarqube/data
          name: data
        - mountPath: /opt/sonarqube/extensions
          name: data
      volumes:
      - name: data
        persistentVolumeClaim:
          claimName: sonarqube-data 
---
apiVersion: v1
kind: Service
metadata:
  name: sonarqube
  namespace: kube-devops
  labels:
    app: sonarqube
spec:
  type: NodePort
  ports:
  - name: sonarqube
    port: 9000
    targetPort: 9000
    protocol: TCP
  selector:
    app: sonarqube

部署

kubectl apply -f sonarqube/

查看

kubectl get pod -n kube-devops

kubectl logs -f sonarqube-58669db48f-kd6c9 -n kube-devops

sonaqube url :192.168.50.76:31223   admin/admin123

2.生成服务token 

# 登录到 sonarqube 后台,点击头像 > MyAccount > Security > Generate Tokens > generate 生成 token 并复制

name输入jenkins

点击生成可得到

sqa_e9c7bfc194603954948b53207b98eca3114036bf

3.创建webhook服务

# 点击顶部菜单栏的配置 > 配置(小三角) > 网络调用

Name:jenkins
URL:http://192.168.50.76:32351/sonarqube-webhook/

URL是jenkins的地址

4.创建项目

# SonarQube 顶部菜单栏 Projects > Create new project > 配置基础信息并保存 > Provide a token > Generate 生成 token > Continue

# 分别选择 Java / Maven 后,按照脚本配置 Jenkinsfile 中的 sonar 配置信息
mvn sonar:sonar -Dsonar.projectKey=k8s-cicd-demo
 

四、Jenkins

1.构建带maven环境的jenkins镜像

dockerfile

FROM jenkins/jenkins:2.462.2-jdk11
ADD ./apache-maven-3.9.0-bin.tar.gz /usr/local/
ADD ./sonar-scanner-4.8.0.2856-linux /usr/local/sonar-scanner

ENV MAVEN_HOME=/usr/local/apache-maven-3.9.0
ENV PATH=$JAVA_HOME/bin:$MAVEN_HOME/bin:$PATH

USER root

RUN echo "jenkins ALL=NOPASSWD: ALL" >> /etc/sudoers
USER jenkins

另外需要准备的是maven的安装包和解压后的sonar安装包

# 构建带 maven 环境的 jenkins 镜像
docker build -t 192.168.50.76:8858/wolfcode/jenkins-maven:v1 .

# 登录 harbor
docker login -uadmin 192.168.50.76:8858
密码是wolfcode

# 推送镜像到 harbor
docker push 192.168.50.76:8858/wolfcode/jenkins-maven:v1

2.安装jenkins

# 进入 jenkins 目录,安装 jenkins
kubectl apply -f manifests/

jenkins-pvc.yaml

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pvc
  namespace: kube-devops
spec:
  storageClassName: managed-nfs-storage
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 1Gi

jenkins-configmap.yaml

apiVersion: v1 
kind: ConfigMap 
metadata: 
  name: mvn-settings
  namespace: kube-devops
  labels: 
    app: jenkins-server
data: 
  settings.xml: |- 
    <?xml version="1.0" encoding="UTF-8"?>
    <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
        <localRepository>/var/jenkins_home/repository</localRepository>
        <servers>
                <server>
                        <id>releases</id>
                        <username>admin</username>
                        <password>wolfcode</password>
                </server>
                <server>
                        <id>snapshots</id>
                        <username>admin</username>
                        <password>wolfcode</password>
                </server>
        </servers>

        <pluginGroups>
                <pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
        </pluginGroups>
        <profiles>
                <profile>
                        <id>releases</id>
                        <activation>
                                <activeByDefault>true</activeByDefault>
                                <jdk>1.8</jdk>
                        </activation>
                        <properties>
                                <sonar.host.url>http://sonarqube:9000</sonar.host.url>
                        </properties>

                </profile>
        </profiles>
    </settings>

jenkins-serviceAccount.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins-admin
  namespace: kube-devops
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: jenkins-admin
  namespace: kube-devops

jenkins-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: kube-devops
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins-server
  template:
    metadata:
      labels:
        app: jenkins-server
    spec:
      serviceAccountName: jenkins-admin
      imagePullSecrets: 
        - name: harbor-secret # harbor 访问 secret
      containers:
        - name: jenkins
          image: 192.168.50.76:8858/wolfcode/jenkins-maven:v1
          imagePullPolicy: IfNotPresent
          securityContext:
            privileged: true
            runAsUser: 0 # 使用 root 用户运行容器
          resources:
            limits:
              memory: "2Gi"
              cpu: "1000m"
            requests:
              memory: "500Mi"
              cpu: "500m"
          ports:
            - name: httpport
              containerPort: 8080
            - name: jnlpport
              containerPort: 50000
          livenessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 90
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: "/login"
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          volumeMounts:
            - name: jenkins-data
              mountPath: /var/jenkins_home
            - name: docker
              mountPath: /run/docker.sock
            - name: docker-home
              mountPath: /usr/bin/docker
            - name: mvn-setting
              mountPath: /usr/local/apache-maven-3.9.0/conf/settings.xml
              subPath: settings.xml
            - name: daemon
              mountPath: /etc/docker/daemon.json
              subPath: daemon.json
            - name: kubectl
              mountPath: /usr/bin/kubectl
      volumes:
        - name: kubectl
          hostPath:
            path: /usr/bin/kubectl
        - name: jenkins-data
          persistentVolumeClaim:
              claimName: jenkins-pvc
        - name: docker
          hostPath:
            path: /run/docker.sock # 将主机的 docker 映射到容器中
        - name: docker-home
          hostPath:
            path: /usr/bin/docker
        - name: mvn-setting
          configMap:
            name: mvn-settings
            items:
            - key: settings.xml
              path: settings.xml
        - name: daemon
          hostPath: 
            path: /etc/docker/

jenkins-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: jenkins-service
  namespace: kube-devops
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/path:   /
      prometheus.io/port:   '8080'
spec:
  selector:
    app: jenkins-server
  type: NodePort
  ports:
    - port: 8080
      targetPort: 8080

# 查看是否运行成功
kubectl get po -n kube-devops

# 查看 service 端口,通过浏览器访问
kubectl get svc -n kube-devops



# 查看容器日志,获取默认密码
kubectl logs -f pod名称 -n kube-devops

url  192.168.50.76:32351   admin/admin

查看密码 cat /var/jenkins_home/secrets/initialAdminPassword

第一次登陆进去会有安装插件推荐,其中github不用,其他默认推荐的都可以装一下

3.安装插件

如果有些插件搜不到,可以去官网下载 https://plugins.jenkins.io/

jenkins界面插件安装入口:dashboard---->manage jenkins---->插件管理

记得以下插件安装完成后点击重启

3.1 build authorization token root

构建授权 token

3.2 gitlab

gitlab 配置插件

3.3 sonarqube scanner

代码质量审查工具
安装好插件后重启jenkins然后配置

1.配置sonarqube凭证

在 Dashboard > 系统管理 >凭据管理>system>全局凭据>添加凭据

类型:scret text

scret: sqa_e9c7bfc194603954948b53207b98eca3114036bf 

这就是上面sonarqube界面里面生成的token

ID: sonarqube-token


2.配置sonarqube server

在 Dashboard > 系统管理 > Configure System 下面配置 SonarQube servers


Name:sonarqube # 注意这个名字要在 Jenkinsfile 中用到
Server URL:http://sonarqube:9000
Server authentication token:创建 credentials 配置为从 sonarqube 中得到的 token

3.(这步没做)进入系统管理 > 全局工具配置 > SonarQube Scanner > Add SonarQube Scanner
Name:sonarqube-scanner
自动安装:取消勾选
SONAR_RUNNER_HOME:/usr/local/sonar-scanner-cli

3.4 node and label parameter

节点标签参数配置

3.5 kubernetes

jenkins + k8s 环境配置


1.配置k8s的节点

进入 Dashboard > 系统管理 > 节点管理 > Configure Clouds 页面


名称:kubernetes
点击 Kubernetes Cloud details 继续配置
Kubernetes 地址:
如果 jenkins 是运行在 k8s 容器中,直接配置服务名即可
https://kubernetes.default


如果 jenkins 部署在外部,那么则不仅要配置外部访问 ip 以及 apiserver 的端口(6443),还需要配置服务证书
Jenkins 地址:
如果部署在 k8s 集群内部:http://jenkins-service.kube-devops
如果在外部:http://192.168.50.76:32479(换成你们自己的)

配置完成后保存即可

2.配置标签

3.6 config file provider 

用于加载外部配置文件,如 Maven 的 settings.xml 或者 k8s 的 kubeconfig 等

3.7 git parameter 

git 参数插件,在进行项目参数化构建时使用

3.8 Pipeline Stage View

阶段试图。构建的时候可以看是一个阶段图,有些阶段需要手动点击触发继续执行,可在这个图中点击。

比如说生成发布的时候cd的时候需要走个流程审批,可以直接在这个上面点

4.创建gitlab访问凭证

系统管理 > 安全 > Manage Credentials > System > 全局凭据(unrestricted) > Add Credentials


范围:全局
用户名:root
密码:wolfcode 我这里是自己的gitlab登录密码,不是这个
ID:gitlab-user-pwd

5.同样的方式创建harbor的凭证

6.添加kubeconfig

把cat ~/.kube/config内的所有内容加进去

五、创建流水线项目

1.在gitlab上创建项目k8s-cicd-demo

具体代码见六、案例

2.在jenkins创建流水线

在首页点击 Create a Job 创建一个流水线风格的项目

配置webhook,当gitlab上有提交则jenkins触发构建

这里选流水线

复制一下地址(这个地址要配置到gitlab上)

GitLab webhook URL: http://192.168.50.76:32351/project/k8s-cicd-demo

复制token  697382bc6acc2f21e0b7e7ee819c58e5

3.在gitlab的项目中配置webhook

4.jenkins构建项目k8s-cicd-demo

发布成功,查看svc对外提供的短空

kubectl get svc -n k8s-cicd-dev

访问192.168.50.76:31691/users

六、案例:springboot项目CICD

项目结构

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.9</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>cn.wolfcode</groupId>
    <artifactId>k8s-cicd-demo</artifactId>
    <version>1.0.0</version>
    <name>k8s-cicd-demo</name>

    <description>K8S CICD 演示项目</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.sonarsource.scanner.maven</groupId>
                    <artifactId>sonar-maven-plugin</artifactId>
                    <version>3.9.1.2184</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

Jenkinsfile

pipeline {
    agent {
        kubernetes {
            label 'maven'
        }
    }

    parameters {
        gitParameter name: 'BRANCH_NAME', branch: '', branchFilter: '.*', defaultValue: 'origin/master', description: '请选择要发布的分支', quickFilterEnabled: false, selectedValue: 'NONE', tagFilter: '*', type: 'PT_BRANCH'
        string(name: 'TAG_NAME', defaultValue: 'snapshot', description: '标签名称,必须以 v 开头,例如:v1、v1.0.0')
    }

    environment {
        DOCKER_CREDENTIAL_ID = 'harbor-user-pass'
        GIT_REPO_URL = '192.168.50.76:28080'
        GIT_CREDENTIAL_ID = 'gitlab-user-pwd'
        GIT_ACCOUNT = 'root' // change me
        KUBECONFIG_CREDENTIAL_ID = '3b0c7b8e-e8db-4d6a-a41f-a3abc7012a56'
        REGISTRY = '192.168.50.76:8858'
        DOCKERHUB_NAMESPACE = 'wolfcode' // change me
        APP_NAME = 'k8s-cicd-demo'
        SONAR_CREDENTIAL_ID = 'sonarqube-token'
    }

    stages {

        stage('checkout scm') {
            steps {
                checkout scmGit(branches: [[name: "$BRANCH_NAME"]], extensions: [], userRemoteConfigs: [[credentialsId: "$GIT_CREDENTIAL_ID", url: 'http://192.168.50.76:28080/root/k8s-cicd-demo.git']])
            }
        }

        stage('unit test') {
            steps {
                sh 'mvn clean test'
            }
        }

        stage('sonarqube analysis') {
            steps {
                withCredentials([string(credentialsId: "$SONAR_CREDENTIAL_ID", variable: 'SONAR_TOKEN')]) {
                    withSonarQubeEnv('sonarqube') {
                        sh 'mvn sonar:sonar -Dsonar.projectKey=$APP_NAME'
                    }
                }
                timeout(time: 1, unit: 'HOURS') {
                    waitForQualityGate abortPipeline: true
                }
            }
        }

        stage('build & push') {
            steps {
                sh 'mvn clean package -DskipTests'
                sh 'docker build -f Dockerfile -t $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BUILD_NUMBER .'
                withCredentials([usernamePassword(passwordVariable: 'DOCKER_PASSWORD', usernameVariable: 'DOCKER_USERNAME', credentialsId: "$DOCKER_CREDENTIAL_ID",)]) {
                    sh 'echo "$DOCKER_PASSWORD" | docker login $REGISTRY -u "$DOCKER_USERNAME" --password-stdin'
                    sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BUILD_NUMBER'
                }
            }
        }

        stage('push latest') {
            steps {
                sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest'
                sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:latest'
            }
        }

        stage('deploy to dev') {
            steps {
                input(id: 'deploy-to-dev', message: 'deploy to dev?')
                sh '''
                    sed -i'' "s#REGISTRY#$REGISTRY#" deploy/cicd-demo-dev.yaml
                    sed -i'' "s#DOCKERHUB_NAMESPACE#$DOCKERHUB_NAMESPACE#" deploy/cicd-demo-dev.yaml
                    sed -i'' "s#APP_NAME#$APP_NAME#" deploy/cicd-demo-dev.yaml
                    sed -i'' "s#BUILD_NUMBER#$BUILD_NUMBER#" deploy/cicd-demo-dev.yaml
                    kubectl apply -f deploy/cicd-demo-dev.yaml
                '''
            }
        }
        stage('push with tag') {
            when {
                expression {
                    return params.TAG_NAME =~ /v.*/
                }
            }
            steps {
                input(id: 'release-image-with-tag', message: 'release image with tag?')
                withCredentials([usernamePassword(credentialsId: "$GIT_CREDENTIAL_ID", passwordVariable: 'GIT_PASSWORD', usernameVariable: 'GIT_USERNAME')]) {
                    sh 'git config --global user.email "liugang@wolfcode.cn" '
                    sh 'git config --global user.name "xiaoliu" '
                    sh 'git tag -a $TAG_NAME -m "$TAG_NAME" '
                    sh 'git push http://$GIT_USERNAME:$GIT_PASSWORD@$GIT_REPO_URL/$GIT_ACCOUNT/k8s-cicd-demo.git --tags --ipv4'
                }
                sh 'docker tag $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:SNAPSHOT-$BUILD_NUMBER $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME'
                sh 'docker push $REGISTRY/$DOCKERHUB_NAMESPACE/$APP_NAME:$TAG_NAME'
            }
        }
        stage('deploy to production') {
            when {
                expression {
                    return params.TAG_NAME =~ /v.*/
                }
            }
            steps {
                input(id: 'deploy-to-production', message: 'deploy to production?')
                sh '''
                    sed -i'' "s#REGISTRY#$REGISTRY#" deploy/cicd-demo.yaml
                    sed -i'' "s#DOCKERHUB_NAMESPACE#$DOCKERHUB_NAMESPACE#" deploy/cicd-demo.yaml
                    sed -i'' "s#APP_NAME#$APP_NAME#" deploy/cicd-demo.yaml
                    sed -i'' "s#TAG_NAME#$TAG_NAME#" deploy/cicd-demo.yaml
                    kubectl apply -f deploy/cicd-demo.yaml
                '''
            }
        }
    }
}

dockerfile

## 基础镜像
## AdoptOpenJDK 停止发布 OpenJDK 二进制,而 Eclipse Temurin 是它的延伸,提供更好的稳定性
FROM eclipse-temurin:8-jre

## 作者
LABEL org.opencontainers.image.authors="liugang@wolfcode.cn"

## 定义参数

## 创建并进入工作目录
RUN mkdir -p /wolfcode
WORKDIR /wolfcode

## maven 插件构建时得到 buildArgs 种的值
COPY target/*.jar app.jar

## 设置 TZ 时区
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms256m -Xmx256m"

## 暴露端口
EXPOSE 8080

## 容器启动命令
## CMD 第一个参数之后的命令可以在运行时被替换
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar

cicd-demo.yaml

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: k8s-cicd-demo
    component: wolfcode-devops
    tier: backend
  name: k8s-cicd-demo
  namespace: k8s-cicd
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  selector:
    matchLabels:
      app: k8s-cicd-demo
      component: wolfcode-devops
      tier: backend
  strategy:
    rollingUpdate:
      maxSurge: 100%
      maxUnavailable: 100%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: k8s-cicd-demo
        component: wolfcode-devops
        tier: backend
    spec:
      imagePullSecrets:
        - name: harbor-secret
      containers:
        - name: k8s-cicd-demo
          image: REGISTRY/DOCKERHUB_NAMESPACE/APP_NAME:TAG_NAME
          readinessProbe:
            httpGet:
              path: /users
              port: 8080
            timeoutSeconds: 10
            failureThreshold: 30
            periodSeconds: 5
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: 300m
              memory: 600Mi
            requests:
              cpu: 100m
              memory: 100Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: k8s-cicd-demo
    component: wolfcode-devops
  name: k8s-cicd-demo
  namespace: k8s-cicd
spec:
  ports:
    - name: http
      port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    app: k8s-cicd-demo
    component: wolfcode-devops
    tier: backend
  sessionAffinity: None
  type: NodePort

cicd-demo-dev.yaml

---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: k8s-cicd-demo
    component: wolfcode-devops
    tier: backend
  name: k8s-cicd-demo
  namespace: k8s-cicd-dev
spec:
  progressDeadlineSeconds: 600
  replicas: 1
  selector:
    matchLabels:
      app: k8s-cicd-demo
      component: wolfcode-devops
      tier: backend
  strategy:
    rollingUpdate:
      maxSurge: 100%
      maxUnavailable: 100%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: k8s-cicd-demo
        component: wolfcode-devops
        tier: backend
    spec:
      imagePullSecrets:
        - name: harbor-secret
      containers:
        - name: k8s-cicd-demo
          image: REGISTRY/DOCKERHUB_NAMESPACE/APP_NAME:SNAPSHOT-BUILD_NUMBER
          readinessProbe:
            httpGet:
              path: /users
              port: 8080
            timeoutSeconds: 10
            failureThreshold: 30
            periodSeconds: 5
          imagePullPolicy: Always
          ports:
            - containerPort: 8080
              protocol: TCP
          resources:
            limits:
              cpu: 300m
              memory: 600Mi
            requests:
              cpu: 100m
              memory: 100Mi
          terminationMessagePath: /dev/termination-log
          terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      terminationGracePeriodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: k8s-cicd-demo
    component: wolfcode-devops
  name: k8s-cicd-demo
  namespace: k8s-cicd-dev
spec:
  ports:
    - name: http
      port: 8080
      protocol: TCP
      targetPort: 8080
  selector:
    app: k8s-cicd-demo
    component: wolfcode-devops
    tier: backend
  sessionAffinity: None
  type: NodePort

K8sCicdDemoApplication.java

package cn.wolfcode;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class K8sCicdDemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(K8sCicdDemoApplication.class, args);
    }

}

UserController.java

package cn.wolfcode.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
@RequestMapping("/users")
public class UserController {

    @GetMapping
    public String users(Integer age) {
        log.info("test: {}", age);
        return "<h1>all users: v1.1.0</h1>";
    }
}

application.yml是空的

K8sCicdDemoApplicationTests.java

package cn.wolfcode;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class K8sCicdDemoApplicationTests {

    @Test
    void contextLoads() {
    }

}

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

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

相关文章

【网络安全】分析JS文件实现账户接管

未经许可,不得转载。 文章目录 正文正文 网站使用的是简单的OTP(一次性密码)验证机制,通过用户注册时提供的电子邮件发送邮箱验证码。在功能有限的情况下,我选择去分析网站加载的JavaScript文件。 我发现了一个名为 saveJobseekerPasswordInCache 的函数: 这个函数虽然…

vscode侧边工具栏不见了找回方法

有时候因为误操作&#xff0c;vscode编辑器里面的侧边工具栏不见了找回方法&#xff0c;请按照以下步骤操作。 例:1&#xff1a;这个工具栏不见了 方法&#xff1a;菜单栏点击文件》点击首选项》点击设置》点击工作台》点击外观》勾选如下图选项 例如2&#xff1a;蓝控制台底…

无人机之穿越机的飞行模式

穿越机的飞行模式主要分为两种基本类型&#xff1a;自稳模式&#xff08;ANGLE MODE&#xff09;和手动模式&#xff08;ACRO MODE&#xff09;&#xff0c;以及一些衍生的飞行模式&#xff0c;如半自稳模式&#xff08;Horizon Mode&#xff09;等。下面将详细介绍这两种基本模…

vulhub think PHP 2-rce远程命令执行漏洞

1.开启环境 2。访问对应网站端口 3.这里我们直接构造payload&#xff0c;访问phpinfo() http://192.168.159.149:8080/?s/Index/index/L/${phpinfo()} 4.可以访问到我们的phpinfo&#xff0c; 所以写入一句话木马&#xff0c;也可使用蚁剑进行连接&#xff0c;获得其shell进…

云计算之大数据(下)

目录 一、Hologres 1.1 产品定义 1.2 产品架构 1.3 Hologres基本概念 1.4 最佳实践 - Hologres分区表 1.5 最佳实践 - 分区字段设置 1.6 最佳实践 - 设置字段类型 1.7 最佳实践 - 存储属性设置 1.8 最佳实践 - 分布键设置 1.9 最佳实践 - 聚簇键设置 1.10 最佳实践 -…

AT3340-6T杭州中科微BDS定位授时板卡性能指标

AT3340-6T是一款高性能多系统卫星定位安全授时板卡&#xff0c;可通过配置支持各个单系统的定位授时。 外观尺寸&#xff1a; 电气参数 应用领域&#xff1a; 通信基站授时 电力授时 广播电视授时 轨道系统授时 金融系统授时 其他授时应用 注意事项&#xff1a; 为了充分发挥…

Linux入门攻坚——31、rpc概念及nfs和samba

NFS&#xff1a;Network File System 传统意义上&#xff0c;文件系统在内核中实现 RPC&#xff1a;函数调用&#xff08;远程主机上的函数&#xff09;&#xff0c;Remote Procedure Call protocol 一部分功能由本地程序完成 另一部分功能由远程主机上的 NFS本质…

软件部署-Docker容器化技术

开始前的环境说明 VMware 17 Pro Centos release 7.9.2009(防火墙已关闭) Docker 26.1.4 Docker镜像加速器配置:"https://do.nark.eu.org", "https://dc.j8.work", "https://docker.m.daocloud.io", "https://dockerproxy.com", &…

2. c#从不同cs的文件调用函数

1.文件目录如下&#xff1a; 2. Program.cs文件的主函数如下 using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms;namespace datasAnalysis {internal static class Program{/// <summary>…

HUAWEI华为MateBook B5-420 i5 集显(KLCZ-WXX9,KLCZ-WDH9)原装出厂Windows10系统文件下载

适用型号&#xff1a;KLCZ-WXX9、KLCZ-WDH9 链接&#xff1a;https://pan.baidu.com/s/12xnaLtcPjZoyfCcJUHynVQ?pwdelul 提取码&#xff1a;elul 华为原装系统自带所有驱动、出厂主题壁纸、系统属性联机支持标志、系统属性专属LOGO标志、华为浏览器、Office办公软件、华为…

网络传输的基本流程

目录 0.前言 1.TCP/IP四层协议模型的认识 2.数据传输的大致流程 3.局域网通信的原理 4.同一网段下两台主机之间的通信 5.不同网段下两台主机之间的通信 0.前言 不知道你有没有这样的疑问&#xff0c;为什么不同的设备之间能够进行数据的发送和接收&#xff1f;不同的通信…

计算机毕业设计选题推荐-农家乐综合服务系统-乡村游乐购系统-田园休闲生活系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…

基于微信小程序+Java+SpringBoot+Vue+MySQL的网上花店/鲜花销售小程序

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于微信小程序JavaSpringBootVueMySQL的网上花店/鲜花销售…

【计算机网络】socket编程 --- 实现简易TCP网络程序

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前正在学习c和算法 ✈️专栏&#xff1a;Linux &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章有啥瑕疵&#xff0c;希望大佬指点一二 如果文章对…

【北京迅为】《STM32MP157开发板使用手册》- 第十二章 编译Linux内核

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…

java黑马微项目

1 飞机票 代码实现&#xff1a; import java.util.Scanner; public class F1 {public static void main(String[] args) {Scanner input new Scanner(System.in);System.out.print("请输入票价&#xff1a; ");double jia input.nextDouble();System.out.print(&…

数据完整性常见缺陷以及对尘埃粒子计数器选择关注点!

数据完整性缺陷的全面回顾性评估 在评估工厂数据完整性缺陷时&#xff0c;首先需要系统地回顾和识别各个环节中可能存在的数据问题。以下是一些常见的与数据完整性相关的缺陷及其描述&#xff1a; 数据遗漏&#xff1a; 记录不全&#xff1a;生产过程中关键步骤或参数的记录…

chatglm4部署以及集成langchain

1.魔塔社区下载glm4 https://modelscope.cn/models/ZhipuAI/glm-4-9b-chat 2.jupyter下载&#xff0c;自己修改下载模型位置 3.环境安装&#xff1a; 本机已经安装了conda,使用conda虚拟环境隔离&#xff0c;就不重复演示了 新项目新激活一个环境&#xff1a;conda create -…

vue3 ts语法在index.ts中vue有红色波浪线

vue.js - Vue 3 with Typescript Could Not Find A Declaration File - Stack Overflow 只要在 vue文件中 写上就好 <script setup lang"ts">

IIS 反向代理模块: URL Rewrite 和 Application Request Routing (ARR)

需要设置iis反向代理的场景其实挺多的。例如websocket、Server Sent Events(SSE) 都需要反向代理。 对于需要临时放公网访问的应用&#xff0c;直接运行127.0.0.1的开发环境&#xff0c;然后通过反向代理访问127.0.0.1就可以了&#xff0c;省去麻烦的iis设置。 IIS 实现反向代…