K8S发布系统-发布访问配置

整合任务

可以将Build和Deploy整合成一个Pipeline任务;同时,若不需要外部调用来触发任务,可以将其中大部分参数固化,一个项目一个任务,以方便用户直接运行。

前端发布

前端采用Node技术开发,故需要在Jenkins上安装Node环境,以进行构建并生成最终的HTML文件;将其添加至 nginx:stable 作为基础镜像来生成项目镜像。

配置Node环境(220.140)

安装:

wget https://nodejs.org/dist/v14.15.4/node-v14.15.4-linux-x64.tar.xz
tar Jxf node-v14.15.4-linux-x64.tar.xz -C /usr/local/
cd /usr/local/
mv node-v14.15.4-linux-x64 nodejs
echo 'PATH=$PATH:/usr/local/nodejs/bin' > /etc/profile.d/nodejs.sh
source /etc/profile.d/nodejs.sh
node -v

安装插件:

npm --registry https://registry.npm.taobao.org install --ensure node-gyp -g
npm --registry https://registry.npm.taobao.org install --unsafe-perm node-sass -g

基础镜像

这里就使用最新的nginx:stable作为源(内部Nginx版本为 18.0),来制作基础镜像:

docker pull nginx:stable
docker history nginx:stable

mkdir ~/baseimg-nginx
cd ~/baseimg-nginx/
vim nginx.conf
# Nginx Main Configure File.
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    gzip  on;

    server {
        listen 8080;

        location /seid {
            add_header "Set-Cookie" "eid=$arg_eid";
            return 200 "success";
        }

        location / {
            root   /data/www/;
            index  index.html index.htm;
            try_files $uri $uri/ /index.html;
        }
    }
}
vim Dockerfile
FROM nginx:stable as build
RUN mkdir -p /data/www && \
    sed -i 's/^# alias/alias/g' ~/.bashrc && \
    sed -i 's/^# export/export/g' ~/.bashrc && \
    sed -i "/^alias mv/a\alias ll='ls -lh --time-style=\"+%Y/%m/%d %H:%M\" --color'" ~/.bashrc
COPY nginx.conf /etc/nginx/nginx.conf
FROM scratch
COPY --from=build / .
LABEL maintainer="Chris"
ENTRYPOINT ["/docker-entrypoint.sh"]
EXPOSE 8080
CMD ["nginx","-g","daemon off;"]
WORKDIR /data
docker build -t baseimg-nginx:1.18 .
docker images

试运行:

docker run --name=nginx --rm -p 8080:8080 -d baseimg-nginx:1.18
dokcer ps

由于现在网站目录为空,访问会出现403;进入Container,生成个页面后刷新:

docker exec -it nginx /bin/bash
echo "Hello, I'm run in docker." > /data/www/index.html

杀掉容器, 标签镜像:

docker kill nginx
docker tag baseimg-nginx:1.18 nw-harbor.xxx.cc/library/baseimg-nginx:1.18
docker images

上传镜像:

docker push nw-harbor.xxx.cc/library/baseimg-nginx:1.18

Tips: Nginx官方的Docker容器中已将日志输出结果重定向到stdout和stderr,故不需再操作

创建任务

创建个Pipeline任务:

node{
    // 用于前端项目(Nginx静态文件), 固化项目配置参数, 每项目一任务, 方便直接执行; 不建议外部调用
  
  // 镜像仓库
  String HarborUrl='nw-harbor.zongs365.cc'
    String HarborUser='admin'
    String HarborPasswd='Nw-Harbor123'
  
  // 构建用: 项目Gitlab地址
  String GIT_URL='http://git.zongsheng.tech/all/demo-front.git'
  // Node NPM 构建用: 配置构建的环境 npm run build:
  String Build_Env='prod'
  // Docker镜像 推送,拉取用: 项目组名称,推送至此Harbor项目组 (e.g: ${HarborUrl}/${Group})
  String Group='zongs-nw'
  // Docker镜像 构建用,部署配置用,Docker镜像 推送,拉取用: 填写项目名称
  String Project_name='demo-front'
  // Docker镜像 构建用: 生成的前端包路径名称
  String Target_name='dist.tar.gz'
  // Docker镜像 构建用: 生成项目Docker镜像的时区
  String TIME_ZONE='Asia/Shanghai'
  // 项目tag(镜像构建的版本; 这里携带Jenkins任务构建版本)
  String Project_Tag="ng-${env.BUILD_NUMBER}"
  
  // 部署配置用: 部署至此命名空间
  String NAMESPACE='default'
  // 部署配置用: 运行的 Pod 数目
  String REPLICAS_NUM='1'
  // 部署配置用: 资源CPU需求
  String REQUESTS_CPU='100m'
  // 部署配置用: 资源Memory需求
  String REQUESTS_MEM='128Mi'
  // 部署配置用: 新创建的Pod状态为Ready持续了此时间后认为Available
  String MINREADSECONDS='5'
  
  // K8S YAML 模板文件所在服务器 (部署,服务模板文件)
  String TemplateUrl='http://172.16.220.105/k8s'
  // K8S Deployment YAML 模板文件名称
  String Temp_Depoly='deployment-front.yaml'
  // K8S Service YAML 模板文件名称
  String Temp_SVC='svc.yaml'
  // K8S 群集 操作主机 (用于SSH连接后执行 kubectl 命令)
  String KubernetHost='[email protected]'
  // 远端 操作主机 存放依模板生成的 YAML 文件
  String Yaml_Path='/root/k8s_deploy'
  // 用于SSH连接到 操作主机 的密钥文件 (若Jenkins运行用户可直接连接,则可留空)
  String SSH_KeyFile='/data/jenkins/.ssh/id_rsa'


  properties([
    parameters([
      string(name: 'GIT_BRANCH', defaultValue: 'master', description: '构建用: 填写Git分支地址', trim: false),
      
      string(name: 'IS_SVC', defaultValue: 'No', description: '部署配置用: 是否创建服务(为 Yes 时部署svc.yaml)', trim: false),
      string(name: 'SVC_PORT', defaultValue: '80', description: '部署配置用: 服务本身监听端口', trim: false),
      string(name: 'TARGETPORT', defaultValue: '8080', description: '部署配置用: 服务后端项目端口(即项目本身所监听的端口)', trim: false)
    ])
  ])

    if(!Project_name){
        error "项目名为空"  
    }
  
  if(SSH_KeyFile){
    if(!fileExists("${SSH_KeyFile}")){
      error "连接密钥文件 ${SSH_KeyFile} 不存在"
    }
    SSH_Command="ssh -i ${SSH_KeyFile} -p 22 -o StrictHostKeyChecking=no"
    SCP_Command="scp -i ${SSH_KeyFile} -P 22 -o StrictHostKeyChecking=no"
  }else{
    SSH_Command="ssh -p 22 -o StrictHostKeyChecking=no"
    SCP_Command="scp -P 22 -o StrictHostKeyChecking=no"
  }

    dir("${env.WORKSPACE}"){
        stage('Git阶段'){
      echo "1. 开始拉取代码 (${GIT_URL})"
            git branch: params.GIT_BRANCH, credentialsId: 'nw-gitlab', url: "${GIT_URL}"
        }
    
        stage('Nodejs阶段'){
            echo "2. 开始 Node npm 编译"
            if(fileExists("${Target_name}")){
        sh "rm -f ${Target_name}"
      }
      sh "npm --registry https://registry.npm.taobao.org install >/dev/null"
      sh "npm run build:${Build_Env}"
      sh "cd ./dist && tar -czf ../${Target_name} ./*"
      sh 'cd ../'
        }
    
        stage('Docker阶段'){
            echo "3. 开始执行Docker编译、推送、删除"
      echo "--生成 Dockerfile"
      sh "echo 'FROM ${HarborUrl}/library/baseimg-nginx:1.18' > Dockerfile"
      sh "echo 'RUN ln -sf /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime' >> Dockerfile"
      sh "echo 'ADD ${Target_name} /data/www/' >> Dockerfile"

            echo "--构建并推送 Docker 镜像 (${HarborUrl}/${Group}/${Project_name}:${Project_Tag})"
      step([$class: 'DockerBuilderPublisher', dockerFileDirectory: "${env.WORKSPACE}", cloud: 'docker_w1', tagsString: "${HarborUrl}/${Group}/${Project_name}:${Project_Tag}", cleanImages: true, cleanupWithJenkinsJobDelete: false, pushCredentialsId: 'nw-harbor', pushOnSuccess: true])
        }
    
    stage('群集主机SSH验证'){
      echo "验证k8s群集内主机 ${KubernetHost} 是否可连通,并确保YAML文件存放目录 ${Yaml_Path}"
      sh "${SSH_Command} ${KubernetHost} mkdir -p ${Yaml_Path}"
    }
    
    stage('K8S-Deployment 配置'){
      echo "从 ${TemplateUrl} 拉取 K8S-Deployment 模板文件"
      sh "wget ${TemplateUrl}/${Temp_Depoly} -O ${Project_name}-deploy.yaml"
      
      echo "按参数配置修改模板文件"
      sh "sed -i 's#CI_PROJECT_NAME#${Project_name}#g' ${Project_name}-deploy.yaml"
      sh "sed -i 's#NAMESPACE#${NAMESPACE}#g' ${Project_name}-deploy.yaml"
      sh "sed -i 's#REPLICAS_NUM#${REPLICAS_NUM}#g' ${Project_name}-deploy.yaml"
      sh "sed -i 's#REPOSITORY_BASE#${HarborUrl}/${Group}#g' ${Project_name}-deploy.yaml"
      sh "sed -i 's#BUILD_IMAGE_VERSION#${Project_Tag}#g' ${Project_name}-deploy.yaml"
      sh "sed -i 's#REQUESTS_CPU#${REQUESTS_CPU}#g' ${Project_name}-deploy.yaml"
      sh "sed -i 's#REQUESTS_MEM#${REQUESTS_MEM}#g' ${Project_name}-deploy.yaml"
      sh "sed -i 's#MINREADSECONDS#${MINREADSECONDS}#g' ${Project_name}-deploy.yaml"
      
      echo "将修改的文件 ${Project_name}-deploy.yaml 传送至 k8s 群集内部机器 ${KubernetHost}"
      sh "${SCP_Command} ${Project_name}-deploy.yaml ${KubernetHost}:${Yaml_Path}"
    }
    
    if(IS_SVC == 'Yes'){
      stage('K8S-SVC 配置(可选项)'){
        echo "从 ${TemplateUrl} 拉取 K8S-SVC 模板文件"
        sh "wget ${TemplateUrl}/${Temp_SVC} -O ${Project_name}-svc.yaml"
        
        echo "按参数配置修改模板文件"
        sh "sed -i 's#CI_PROJECT_NAME#${Project_name}#g' ${Project_name}-svc.yaml"
        sh "sed -i 's#NAMESPACE#${NAMESPACE}#g' ${Project_name}-svc.yaml"
        sh "sed -i 's#SVC_PORT#${SVC_PORT}#g' ${Project_name}-svc.yaml"
        sh "sed -i 's#TARGETPORT#${TARGETPORT}#g' ${Project_name}-svc.yaml"
        
        echo "将修改的文件 ${Project_name}-svc.yaml 传送至 k8s 群集内部机器 ${KubernetHost}"
        sh "${SCP_Command} ${Project_name}-svc.yaml ${KubernetHost}:${Yaml_Path}"
      }
    }
    
    stage('部署至K8S'){
      echo "部署应用 ${Project_name}-deploy.yaml"
      sh "${SSH_Command} ${KubernetHost} kubectl apply -f ${Yaml_Path}/${Project_name}-deploy.yaml"
      if(IS_SVC == 'Yes'){
        echo "部署服务 ${Project_name}-svc.yaml"
        sh "${SSH_Command} ${KubernetHost} kubectl apply -f ${Yaml_Path}/${Project_name}-svc.yaml"
      }
    }
    }
}

同样的,第一次执行会失败,主要是因为IS_SVC参数需要提供,前面构建均正常:

再次执行,初次部署,将IS_SVC设为Yes,以创建服务:

执行成功:

K8S上验证:

kubectl get deployments.apps
kubectl get pods
kubectl get svc

发表评论

error: Content is protected !!