zoukankan      html  css  js  c++  java
  • k8s+jenkins:部署SpringCloud微服务

    接着上一篇:https://www.cnblogs.com/wwjj4811/p/14590698.html

    拉取代码,构建镜像

    配置nfs

    vi /etc/exports
    
    /opt/nfs/jenkins *(rw,no_root_squash)
    /opt/nfs/maven   *(rw,no_root_squash)
    
    systemctl restart nfs
    mkdir -p /opt/nfs/maven
    chown -R jenkins:jenkins /opt/nfs/maven
    chmod -R 777 /opt/nfs/maven
    #这里有点坑,卡了我很长时间,需要给docker.sock777权限,不然jenkins用户无法执行docker命令
    #并且这里需要把每一台k8s机器的docker.sock赋权
    cd /run/
    chmod 777 docker.sock
    

    配置流水线项目

    创建harbor凭证

    image-20210329092225672

    新建一个流水线项目,配置参数化构建

    image-20210329091916259 image-20210329091931698

    添加文本参数:

    image-20210329093153918

    配置流水线脚本:

    def git_address = "http://192.168.1.50:82/root/tensquare_back.git"
    def git_auth = "070a1a0f-6f41-4b47-8b4e-9621087df6fd"
    //构建版本的名称
    def tag = "latest"
    //Harbor私服地址
    def harbor_url = "192.168.1.52:85"
    //Harbor的项目名称
    def harbor_project_name = "tensquare"
    //Harbor的凭证
    def harbor_auth = "067c32d4-92d1-4d73-bd8b-853dbb5186ee"
    //pod模板
    podTemplate(label: 'jenkins-slave', cloud: 'kubernetes', containers: [
    	containerTemplate(
    		name: 'jnlp',
    		image: "192.168.1.52:85/library/jenkins-slave-maven:lasted"
    	),
    	containerTemplate(
    		name: 'docker',
    		image: "docker:stable",
    		ttyEnabled: true,
    		command: 'cat'
    	),
    ],
    volumes: [
    	hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
    	nfsVolume(mountPath: '/usr/local/apache-maven/repo', serverAddress: '192.168.1.36' , serverPath: '/opt/nfs/maven'),
    ],
    )
    {
    node("jenkins-slave"){
    // 第一步
    	stage('拉取代码'){
    		checkout([$class: 'GitSCM', branches: [[name: '${branch}']],
    		userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
    	}
    	// 第二步
    	stage('代码编译'){
    		//编译并安装公共工程
    		sh "mvn -f tensquare_common clean install"
    	}
    // 第三步
    stage('构建镜像,部署项目'){
    	//把选择的项目信息转为数组
    	def selectedProjects = "${project_name}".split(',')
    	for(int i=0;i<selectedProjects.size();i++){
    		//取出每个项目的名称和端口
    		def currentProject = selectedProjects[i];
    		//项目名称
    		def currentProjectName = currentProject.split('@')[0]
    		//项目启动端口
    		def currentProjectPort = currentProject.split('@')[1]
    		//定义镜像名称注意:在构建过程会发现无法创建仓库目录,是因为NFS共享目录权限不足,需更改权限
    		//还有Docker命令执行权限问题
    		//需要手动上传父工程依赖到NFS的Maven共享仓库目录中
    		//微服务部署到K8S
    		def imageName = "${currentProjectName}:${tag}"
    		//编译,构建本地镜像
    		sh "mvn -f ${currentProjectName} clean package dockerfile:build"
    		container('docker') {
    			//给镜像打标签
    			sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
    			//登录Harbor,并上传镜像
    			withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]){
    				//登录
    				sh "docker login -u ${username} -p ${password} ${harbor_url}"
    				//上传镜像
    				sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
    			}
    			//删除本地镜像
    			sh "docker rmi -f ${imageName}"
    			sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
    		}
    	}
    }
    }
    }
    
    
    image-20210329092358804

    保存,然后我们测试注册中心的构建:

    image-20210329093452969

    等待一段时间,第一次部署,会安装许多maven依赖。

    image-20210329111028805

    安装Kubernetes Continuous Deploy插件

    image-20210329111540028

    安装完成后,重启jenkins。

    获取k8s的token

    cd ~/.kube/
    cat config
    

    image-20210329112511516

    创建k8s凭证:把上面config文件的内容复制到content中

    image-20210329112542945

    image-20210329112700461

    修改流水线脚本

    def git_address = "http://192.168.1.50:82/root/tensquare_back.git"
    def git_auth = "070a1a0f-6f41-4b47-8b4e-9621087df6fd"
    //构建版本的名称
    def tag = "latest"
    //Harbor私服地址
    def harbor_url = "192.168.1.52:85"
    //Harbor的项目名称
    def harbor_project_name = "tensquare"
    //Harbor的凭证
    def harbor_auth = "067c32d4-92d1-4d73-bd8b-853dbb5186ee"
    def k8s_auth = "f8de51c5-6d18-4f5b-8e8a-b645f45a750e"
    //定义k8s-harbor的凭证
    def secret_name = "registry-auth-secret"
    //pod模板
    podTemplate(label: 'jenkins-slave', cloud: 'kubernetes', containers: [
    	containerTemplate(
    		name: 'jnlp',
    		image: "192.168.1.52:85/library/jenkins-slave-maven:lasted"
    	),
    	containerTemplate(
    		name: 'docker',
    		image: "docker:stable",
    		ttyEnabled: true,
    		command: 'cat'
    	),
    ],
    volumes: [
    	hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),
    	nfsVolume(mountPath: '/usr/local/apache-maven/repo', serverAddress: '192.168.1.36' , serverPath: '/opt/nfs/maven'),
    ],
    )
    {
    node("jenkins-slave"){
        // 第一步
    	stage('拉取代码'){
    		checkout([$class: 'GitSCM', branches: [[name: '${branch}']],userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])
    	}
    	// 第二步
    	stage('代码编译'){
    		//编译并安装公共工程
    		sh "mvn -f tensquare_common clean install"
    	}
    // 第三步
    stage('构建镜像,部署项目'){
    	//把选择的项目信息转为数组
    	def selectedProjects = "${project_name}".split(',')
    	for(int i=0;i<selectedProjects.size();i++){
    		//取出每个项目的名称和端口
    		def currentProject = selectedProjects[i];
    		//项目名称
    		def currentProjectName = currentProject.split('@')[0]
    		//项目启动端口
    		def currentProjectPort = currentProject.split('@')[1]
    		def imageName = "${currentProjectName}:${tag}"
    		//编译,构建本地镜像
    		sh "mvn -f ${currentProjectName} clean package dockerfile:build"
    		container('docker') {
    			//给镜像打标签
    			sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"
    			//登录Harbor,并上传镜像
    			withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]){
    				//登录
    				sh "docker login -u ${username} -p ${password} ${harbor_url}"
    				//上传镜像
    				sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"
    			}
    			//删除本地镜像
    			sh "docker rmi -f ${imageName}"
    			sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"
    		}
    		def deploy_image_name = "${harbor_url}/${harbor_project_name}/${imageName}"
            //部署到K8S
            sh """
                sed -i 's#$IMAGE_NAME#${deploy_image_name}#' ${currentProjectName}/deploy.yml
                sed -i 's#$SECRET_NAME#${secret_name}#' ${currentProjectName}/deploy.yml
            """
            kubernetesDeploy configs: "${currentProjectName}/deploy.yml", kubeconfigId: "${k8s_auth}"
    
    	}
    }
    }
    }
    

    配置deploy.yml

    放到eureka项目的根路径下面:

    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: eureka
      labels:
        app: eureka
    spec:
      type: NodePort
      ports:
        - port: 10086
          name: eureka
          targetPort: 10086
      selector:
        app: eureka
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: eureka
    spec:
      serviceName: "eureka"
      replicas: 2
      selector:
        matchLabels:
          app: eureka
      template:
        metadata:
          labels:
            app: eureka
        spec:
          imagePullSecrets:
            - name: $SECRET_NAME
          containers:
            - name: eureka
              image: $IMAGE_NAME
              ports:
                - containerPort: 10086
              env:
                - name: MY_POD_NAME
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.name
                - name: EUREKA_SERVER
                  value: "http://eureka-0.eureka:10086/eureka/,http://eureka-1.eureka:10086/eureka/"
                - name: EUREKA_INSTANCE_HOSTNAME
                  value: ${MY_POD_NAME}.eureka
      podManagementPolicy: "Parallel"
    
    

    修改application.yml

    server:
      port: ${PORT:10086}
    spring:
      application:
        name: eureka
    
    eureka:
      server:
        # 续期时间,即扫描失效服务的间隔时间(缺省为60*1000ms)
        eviction-interval-timer-in-ms: 5000
        enable-self-preservation: false
        use-read-only-response-cache: false
      client:
        # eureka client间隔多久去拉取服务注册信息 默认30s
        registry-fetch-interval-seconds: 5
        serviceUrl:
          defaultZone: ${EUREKA_SERVER:http://127.0.0.1:${server.port}/eureka/}
      instance:
        # 心跳间隔时间,即发送一次心跳之后,多久在发起下一次(缺省为30s)
        lease-renewal-interval-in-seconds: 5
        # 在收到一次心跳之后,等待下一次心跳的空档时间,大于心跳间隔即可,即服务续约到期时间(缺省为90s)
        lease-expiration-duration-in-seconds: 10
        instance-id: ${EUREKA_INSTANCE_HOSTNAME:${spring.application.name}}:${server.port}@${random.long(1000000,9999999)}
        hostname: ${EUREKA_INSTANCE_HOSTNAME:${spring.application.name}}
    

    生成docker凭证

    k8s master执行:

    docker login -u admin -p Harbor12345 192.168.1.52:85
    #生成证书
    kubectl create secret docker-registry registry-auth-secret --docker-server=192.168.1.52:85 --docker-username=admin --docker-password=Harbor12345 --docker-email=wj@qq.com
    #查看密钥
    kubectl get secret 
    

    image-20210329123408077

    测试部署

    image-20210329124335901

    image-20210329124408657

    访问集群暴露的30876端口

    image-20210329124444112

    可以看到,两个eureka实例分散的部署到node1和node2节点了

    image-20210329124559779

    测试部署服务网关zuul

    修改zuul网关的eureka连接配置:

    image-20210329124741140

    网关的deploy.yml文件,放到网关服务的根目录下

    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: zuul
      labels:
        app: zuul
    spec:
      type: NodePort
      ports:
        - port: 10020
          name: zuul
          targetPort: 10020
      selector:
        app: zuul
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: zuul
    spec:
      serviceName: "zuul"
      replicas: 2
      selector:
        matchLabels:
          app: zuul
      template:
        metadata:
          labels:
            app: zuul
        spec:
          imagePullSecrets:
            - name: $SECRET_NAME
          containers:
            - name: zuul
              image: $IMAGE_NAME
              ports:
                - containerPort: 10020
      podManagementPolicy: "Parallel"
    

    测试部署网关:

    image-20210329125033142

    image-20210329125308489

    image-20210329125333336

    网关服务注册到eureka:

    image-20210329125404745

  • 相关阅读:
    2020软件工程个人作业06————软件工程实践总结作业
    2020软件工程作业01
    班级博客V2.1版本更新日志
    博客园班级手机版
    班级帮助文档
    问题累计
    2020 软件工程作业06
    2020 软件工程作业04
    2020 软件工程作业03
    2020软件工程02
  • 原文地址:https://www.cnblogs.com/wwjj4811/p/14591873.html
Copyright © 2011-2022 走看看