joeの小窝

Loading...

cicd实战

cicd实验1:

图解

img

环境:

2个仓库,test,deploy

  • test仓库,go代码

  • deploy仓库,dockerfile文件(基于编译好的go代码构建镜像),部署文件

jenkins
kubernetes
gitee
harbor

实验流程

问题:test上有一个go代码,需要将其编译,推送到harbor仓库上,拉取这个harbor仓库镜像,部署到k8s节点上

  • 不要小看这几句话,涉及到的操作非常的多

  • 首先就是jenkins连接gitee,harbor,需要创建2个凭证,拉取代码,推送构建好的镜像到harbor

  • 自己构建带有go环境的镜像,需要编译go代码为二进制文件

  • 拉取deploy仓库,里面有dockerfile文件(将编译好的二进制文件构建成镜像),部署文件

  • 自己构建一个docker环境的镜像,构建编译好的镜像,推送到harbor仓库

  • 构建一个带有kubectl环境的镜像,部署文件

1、go代码文件

一个go编写的应用程序

package main

import (
	"fmt"
	"net/http"
)

// 处理函数:访问 / 时返回 hello world
func helloHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintln(w, "hello world")
}

func main() {
	// 绑定路由:访问 http://localhost:8080 就触发 helloHandler
	http.HandleFunc("/", helloHandler)

	fmt.Println("服务启动成功,监听端口 8080")
	fmt.Println("访问地址:http://127.0.0.1:8080")

	// 监听 0.0.0.0:8080
	err := http.ListenAndServe(":8080", nil)
	if err != nil {
		fmt.Println("服务启动失败:", err)
	}
}

2、构建go环境镜像

[root@master01 dockerimage]# ls
dockerfile  openEuler.repo
[root@master01 dockerimage]# cat dockerfile 
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/openeuler/openeuler:22.03-lts-sp4
COPY ./openEuler.repo /etc/yum.repos.d/
RUN set -ex; \
yum -y install tar curl ; \
curl https://mirrors.aliyun.com/golang/go1.16.9.linux-amd64.tar.gz -O ; \
tar -xf go1.16.9.linux-amd64.tar.gz -C /usr/local/ 
ENV GO_HOME=/usr/local/go
ENV PATH=$PATH:$GO_HOME/bin

RUN go version 

# 推送到harbor仓库

3、编译go代码

pipeline {
    agent {
        kubernetes {
            cloud "k8s"
            showRawYaml true
            yaml """
apiVersion: "v1"
kind: "Pod"
metadata:
  name: "go"
  namespace: "devops"
spec:
  serviceAccount: jenkins-admin   // 用户为jenkins-admin
  securityContext:
    runAsUser: 0  // 提权为root
  volumes:
  - name: localtime
    hostPath:
      path: /etc/localtime
  containers:
  - name: jnlp
    image: jenkins/inbound-agent
    args: ['\$(JENKINS_SECRET)', '\$(JENKINS_NAME)']
  - command:
    - "cat"
    image: "192.168.50.21:5000/jichu/go:v1"    // 拉取镜像
    name: "go"
    tty: true
    volumeMounts:
    - mountPath: "/etc/localtime"
      name: "localtime"


"""
        }
    }

    options {  // 选项参数
        timestamps()
        skipDefaultCheckout()
        disableConcurrentBuilds()
        timeout(time: 1, unit: 'HOURS')
    }

    stages {
        stage("获取代码") {
            steps {
                echo "git拉取go代码....."   // 通过流水线语法,自动生成拉取gitee仓库代码
                git changelog: false, credentialsId: '1', poll: false, url: 'https://gitee.com/qw_97/test.git'
            }
        }

        stage("执行编译go代码") {
            steps {
                container("go") {  // 编译go代码
                    sh '''
                        go mod init test
                        go mod tidy
                        /usr/local/go/bin/go build -o code .  
                        ls -lh ./   
                    ''' 
                }
            }
        }

    }
}

4、构建docker环境镜像

[root@master01 dockerimage]# ls
dockerfile  openEuler.repo
[root@master01 dockerimage]# cat dockerfile 
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/openeuler/openeuler:22.03-lts-sp4
COPY ./openEuler.repo /etc/yum.repos.d/
RUN set -ex; \
yum -y install docker; \

# 推送到harbor
  • 容器还需要挂载docker.sock文件,因为是一个c/s架构,使用docker命令的时候需要去连接服务端

5、构建编译好的go文件为镜像

deploy仓库下有dockerfile文件

FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/openeuler/openeuler:22.03-lts-sp4
RUN set -ex; \
  mkdir -p /apps
COPY code /apps/code
EXPOSE 8080
CMD ["/apps/code"]

pipeline {
    agent {
        kubernetes {
            cloud "k8s"
            showRawYaml true
            yaml """
apiVersion: "v1"
kind: "Pod"
metadata:
  name: "go"
  namespace: "devops"
spec:
  serviceAccount: jenkins-admin
  securityContext:
    runAsUser: 0
  volumes:
  - name: localtime
    hostPath:
      path: /etc/localtime
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
  containers:
  - name: jnlp
    image: jenkins/inbound-agent
    args: ['\$(JENKINS_SECRET)', '\$(JENKINS_NAME)']
  - command:
    - "cat"
    image: "192.168.50.21:5000/jichu/go:v1"
    name: "go"
    tty: true
    volumeMounts:
    - mountPath: "/etc/localtime"
      name: "localtime"
  - command:
    - "cat"
    image: "192.168.50.21:5000/jichu/docker:v1"
    name: "docker"
    tty: true
    volumeMounts:
    - mountPath: "/etc/localtime"
      name: "localtime"
    - name: docker-sock
      mountPath: /var/run/docker.sock    // docker.sock挂载
  - command:
    - "cat"
    image: "192.168.50.21:5000/jichu/kubectl:v1.23.0"
    name: "kubectl"
    tty: true
    volumeMounts:
    - mountPath: "/etc/localtime"
      name: "localtime"
"""
        }
    }

    options {
        timestamps()
        skipDefaultCheckout()
        disableConcurrentBuilds()
        timeout(time: 1, unit: 'HOURS')
    }

    environment {   // 定义环境变量,连接harbor仓库的
        registry_account = credentials("2") 
    } 

    stages {
        stage("获取代码") {
            steps {
                echo "git拉取go代码....."
                git changelog: false, credentialsId: '1', poll: false, url: 'https://gitee.com/qw_97/test.git'
            }
        }

        stage("执行编译go代码") {
            steps {
                container("go") {
                    sh '''
                        go mod init test
                        go mod tidy
                        /usr/local/go/bin/go build -o code .
                        ls -lh ./
                    '''
                }
            }
        }

        stage("构建镜像") {
            steps {
                git changelog: false, credentialsId: '1', poll: false, url: 'https://gitee.com/qw_97/deploy.git'   // 拉取deploy仓库代码,里面有dockerfile文件,部署文件
                
                container("docker") {
                    sh "docker login -u ${registry_account_USR} -p ${registry_account_PSW} 192.168.50.21:5000"  // 登录harbor仓库
                    sh "docker -v"
                    
                    sh "docker build -t webapp:v1 . -f dockerfile"   // 构建镜像
                    sh "docker tag webapp:v1 192.168.50.21:5000/jichu/webapp:v1"  
                    sh "docker push 192.168.50.21:5000/jichu/webapp:v1"  // 推送镜像到harbor
                }
            }
        }
        
    }
}

6、构建带有kubectl环境镜像

  • kubectl 二进制文件,直接拷贝即可,需要使用config文件

  • 其实这一步可以放在构建docker环境镜像里面,这样的话就不需要在启动一个容器部署

  • 但是了linux就是一个任务就干一件事

[root@master01 kuebctl]# ls
dockerfile  kubectl
[root@master01 kuebctl]# cat dockerfile 
FROM swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/openeuler/openeuler:22.03-lts-sp4
COPY ./kubectl /usr/bin/kubectl   # 需要这个授权文件,才能控制k8s集群
RUN set -ex; \
  chmod +x /usr/bin/kubectl

# 推送到harbor仓库上

7、部署到k8s节点

pipeline {
    agent {
        kubernetes {
            cloud "k8s"
            showRawYaml true
            yaml """
apiVersion: "v1"
kind: "Pod"
metadata:
  name: "go"
  namespace: "devops"
spec:
  serviceAccount: jenkins-admin
  securityContext:
    runAsUser: 0
  volumes:
  - name: localtime
    hostPath:
      path: /etc/localtime
  - name: docker-sock
    hostPath:
      path: /var/run/docker.sock
  containers:
  - name: jnlp
    image: jenkins/inbound-agent
    args: ['\$(JENKINS_SECRET)', '\$(JENKINS_NAME)']
  - command:
    - "cat"
    image: "192.168.50.21:5000/jichu/go:v1"
    name: "go"
    tty: true
    volumeMounts:
    - mountPath: "/etc/localtime"
      name: "localtime"
  - command:
    - "cat"
    image: "192.168.50.21:5000/jichu/docker:v1"
    name: "docker"
    tty: true
    volumeMounts:
    - mountPath: "/etc/localtime"
      name: "localtime"
    - name: docker-sock
      mountPath: /var/run/docker.sock
  - command:
    - "cat"
    image: "192.168.50.21:5000/jichu/kubectl:v1.23.1"
    name: "kubectl"
    tty: true
    volumeMounts:
    - mountPath: "/etc/localtime"
      name: "localtime"
"""
        }
    }

    options {
        timestamps()
        skipDefaultCheckout()
        disableConcurrentBuilds()
        timeout(time: 1, unit: 'HOURS')
    }

    environment {
        registry_account = credentials("2")
    } 

    stages {
        stage("获取代码") {
            steps {
                echo "git拉取go代码....."
                git changelog: false, credentialsId: '1', poll: false, url: 'https://gitee.com/qw_97/test.git'
            }
        }

        stage("执行编译go代码") {
            steps {
                container("go") {
                    sh '''
                        go mod init test
                        go mod tidy
                        /usr/local/go/bin/go build -o code .
                        ls -lh ./
                    '''
                }
            }
        }

        stage("构建镜像") {
            steps {
                git changelog: false, credentialsId: '1', poll: false, url: 'https://gitee.com/qw_97/deploy.git'
                
                container("docker") {
                    sh "docker login -u ${registry_account_USR} -p ${registry_account_PSW} 192.168.50.21:5000"
                    sh "docker -v"
                    
                    sh "docker build -t webapp:v1 . -f dockerfile"
                    sh "docker tag webapp:v1 192.168.50.21:5000/jichu/webapp:v1"
                    sh "docker push 192.168.50.21:5000/jichu/webapp:v1"
                }
            }
        }
        
        stage("部署应用"){
            steps {
                container("kubectl") {
                    sh "kubectl --kubeconfig config apply -f webapp.yml"
                    sh "kubectl --kubeconfig config apply -f webapp-svc.yml"
                }
            }
        }
    }
}

8、构建好的镜像推送到仓库上

  • 可以自己运行一下,看是否构建正常
[root@master01 deploy]# docker ps -a| grep webapp
68137984f3fa        192.168.50.21:5000/jichu/webapp:v1                         "/apps/code"             4 seconds ago       Up 3 seconds               0.0.0.0:8080->8080/tcp   webapp1

# 访问
[root@master01 deploy]# curl localhost:8080
hello world

# 构建的镜像是可以访问的,没有任何问题

容器实验环境

可以根据自己的需求构建各种不同的镜像环境

  • 构建一个docker镜像容器环境

  • 构建一个ssh免密登录镜像容器环境

posted @ 2026-04-16 23:23  乔的港口  阅读(17)  评论(0)    收藏  举报