花顿饭钱,入坑cicd 上(jenkins、nginx、Nexus准备)

646 阅读5分钟

最近学习ks8心得汇总,同时将遇到的问题全部记录,你看完跟着文章走也可以从0部署一套cicd.

涉及核心

  • docker
  • jenkins
  • Kubernetes
  • nginx
  • Nexus
  • 主要从2个方面讲述,第一个是前期准备,每个软件安装、基本使用。第二个是整体的串联(贴合实际工作 ),部署一套前后端分离项目。(前提会一点 lunix 的基本命令)

硬件

  • 我用的云服务器,一共4台服务器,2台(2c4g),2台(1c2g),推荐买临时的不用了就断开,玩的时候在开启(穷的办法)
    • 1台2c4g 用来部署 Kubernetes(master)
    • 1台2c4g 用来部署 Nexus&jenkins(纯粹为了省钱)
    • 2台1c2g 用来部署 Kubernetes(pod)

软件

docker

centos7.2中安装docker

-   yum -y install docker-io
-   docker version
-   docker info
-   启动docker服务 systemctl start docker
  • 阿里云加速
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://fwvjnv59.mirror.aliyuncs.com"]
}
EOF
// 重新加载某个服务的配置文件,如果新安装了一个服务,归属于 systemctl 管理,要是新服务的服务程序配置文件生效,需重新加载。
systemctl daemon-reload
// 重启docker服务
systemctl restart docker

image

  • git 和 svn 原理
    • svn 每次变化,他会把文件生成一个快照 保存起来
    • git 每次变化,仓库内存的只是相对上一次变化的内容 保存起来
  • 基本操作
  • 镜像: 后面的默认是latest(默认最新,不是最新则要加版本号) | 命令 | 含义 | 案例| | ----------- | ----------| ---- | | images | 查看全部镜像 | docker image ls| | search | 查找镜像 | docker search [imageName]| | pull | 拉取镜像 | docker image pull [imageName]| | rmi | 删除镜像 | docker image rmi [imageName]| | inspect | 镜像信息 | docker image rmi [imageName]| | tag | 镜像取名字(会多一条记录) | docker image tag [imageName] [myName]:latest(版本)|

容器

  • docker container run hello-world 他会生成一个 容器,只打印一下日志就关闭(能启动后台服务的容器就不会关闭)
  • 后缀 添加 -a 显示所有容器
  • 后缀 -l 显示最新的容器
命令含义案例
run从镜像运行一个容器docker container run ubuntu /bin/echo 'hello-world'
--rm运行完自动删除docker container run --rm ubuntu /bin/bash
ps查看当前运行的容器docker container ps -a -l
ls查看所有容器docker container ls -a
inspect查看容器信息docker container inspect [containerId]
kill [containerId]终止容器(发送SIGKILL )docker kill [containerId]
rm [containerId]删除容器docker rm [containerId]
start [containerId]启动已经生成、已经停止运行的容器文件docker start [containerId]
stop [containerId]终止容器运行 (发送 SIGTERM )docker stop [containerId]
logs [containerId]查看 docker 容器的输出docker logs --follow [containerId]
attach [containerId]进入容器docker attach [containerId]
run [containerId]进入一个正在运行的 docker 容器docker container run -it [container] /bin/bash(最后这个是执行的命令)
exitdocker 容器退出exit
cp [containerId]从正在运行的 Docker 容器里面,将文件拷贝到本机docker container cp [containID]:app/package.json

制作镜像 && 使用

制作个性化镜像
    docker commit -m"hello" -a "sg" [containerId] sg/hello:latest
    docker images
    docker run sg/hello /bin/bash

制作Dockerfile

  • Docker 的镜像是用一层一层的文件组成的
  • docker inspect命令可以查看镜像或者容器
  • Layers就是镜像的层文件,只读不能修改。基于镜像创建的容器会共享这些文件层
  • .dockerignore(忽略文件)
    • .git
    • node_modules

tip 编写Dockerfile

命令含义案例
FROM继承的镜像FROM node
COPY拷贝COPY ./app /app
WORKDIR指定工作路径WORKDIR /app
RUN编译打包阶段运行命令RUN npm install
EXPOSE暴露端口EXPOSE 3000
CMD容器运行阶段运行命令CMD npm run start

Dockerfile编写例子 && 使用

1、node 安装
    wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash
    source ~/.bashrc
    nvm install stable
    node -v
    npm i cnpm -g
    npm i nrm -g

    文件传输要安装 rz
    yum install lrzsz
 
    service nginx status //查看nginx开启状态
    service nginx start
    
    // 使用lsof
    yum install lsof
    lsof -i:8080 //查看8080端口
  
    // 杀进程
    kill -s 9 进程号

    // 开启服务 后台运行
    node serve.js &

    // 安装 git
    yum install -y git
    // 创建git用户
    useradd git
    passwd git
2、安装express
    npm install express-generator -g
    express app

3、Dockerfile
    vim Dockerfile
    写入 
        FROM node
        COPY ./app /app
        WORKDIR /app
        RUN npm install
        EXPOSE 3000
4、运行 docker build -t express-demo .
-t用来指定image镜像的名称,后面还可以加冒号指定标签,如果不指定默认就是latest
.表示Dockerfile文件的所有路径,.就表示当前路径

5、使用
- -p 端口映射(容器内的端口映射到主机,p是publish-port缩写)
docker container run -p 3333:3000 -it express-demo /bin/bash
-  容器 的nginx 80端口 映射主机的8080端口,有人访问了主机的8080端口 他会映射到容器的80端口
docker run -p 8080:80 nginx
- -d 后台运行
docker run -d -p 8080:80 nginx
- top 查看进程 containerId只需要输入部分
docker container top [containerId]
- 一般一个服务对应一个docker 容器

6、发布
docker login
docker image tag [north_uc_1] [username]/[repository]:[tag]
docker image build -t [username]/[repository]:[tag] .
docker tag express-demo songge/express-demo:1.0.0
docker push songge/express-demo:1.0.0

Nexus(私服)

  • 部署 Nexus 服务
  • nexus-3.29.0-02 是nexus主程序文件夹
  • sonatype-work 则是数据文件
  • nexus 还支持停止,重启等命令。可以在 bin 目录下执行 ./nexus help 查看更多命令
cd /usr/local
wget https://dependency-fe.oss-cn-beijing.aliyuncs.com/nexus-3.29.0-02-unix.tar.gz
tar -zxvf ./nexus-3.29.0-02-unix.tar.gz
cd nexus-3.29.0-02/bin
./nexus start

firewall-cmd --zone=public --add-port=8081/tcp --permanent
firewall-cmd --zone=public --add-port=8082/tcp --permanent

http://8.144.177.239:8081/

配置 Nexus

  • 可以使用admin用户登录Nexus
  • 注意请立即更改密码
  • Enable anonymous access
cat /root/sonatype-work/nexus3/admin.password 

创建Docker私服

  • 密码:Sg920322
  • 登录 => 齿轮图标 => Repositories => Create repository => docker(hosted) => HTTP(8082)
    • 8082 修改仓库的port 默认是8081
  • proxy: 此类型制品库原则上只下载,不允许用户推送
  • hosted:此类型制品库和 proxy 相反,原则上 只允许用户推送,不允许缓存。这里只存放自己的私有镜像或制品
  • group:此类型制品库可以将以上两种类型的制品库组合起来

添加访问权限

登录制品库

  • 默认情况下不能识别http协议的 他认为不安全 需要加下面配置 ip是仓库地址
  • vi /etc/docker/daemon.json
{
  # 通过https 请求
  "insecure-registries" : [
    "8.144.177.239:8082"
  ],
  "registry-mirrors": ["https://fwvjnv59.mirror.aliyuncs.com"]
}

systemctl restart docker # 记得要重启
docker login 8.142.41.191:8082 //注意此处要和insecure-registries里的地址一致
Username: xxx
Password: xxxxx

推送镜像到制品库

  • 设置界面 => 构建环境 => 勾选 Use secret text(s) or file(s) => 新增选择 => Username and password (separated)
  • DOCKER_LOGIN_USERNAME
  • DOCKER_LOGIN_PASSWORD
  • 接着在下面指定凭据=>添加jenkins=>选择类型Username with password,输入用户名和密码然后点添加确定
  • 打包的时候 一定要吧ip:port携带上 例如:8.142.41.191:8082/xxx,如果不带 push不了
#!/bin/sh -l

npm install --registry=https://registry.npm.taobao.org
npm run build
time=$(date "+%Y%m%d%H%M%S")DOCKER_LOGIN_PASSWORD
# 在nexus 上会分层显示
# 8.142.41.191:8082 ip
# cicd-backend 镜像名字
# target $time 
docker build -t 8.142.41.191:8082/cicd-backend:$time .
docker login -u $DOCKER_LOGIN_USERNAME -p $DOCKER_LOGIN_PASSWORD 8.142.41.191:8082
docker push 8.142.41.191:8082/cicd-backend:$time
  • 然后就可以查看镜像了,注意端口是8081

拉取私有镜像

docker pull 8.144.177.239:8082/xxx

nginx

  • 安装模块
  • yum -y install gcc gcc-c++ autoconf pcre pcre-devel make automake
  • yum -y install wget httpd-tools vim
  • nginx安装文档

CentOS下YUM安装

vim 
    /etc/yum.repos.d/nginx.repo

写入:
    [nginx]
    name=nginx repo
    baseurl=http://nginx.org/packages/centos/7/$basearch/
    gpgcheck=0
    enabled=1

运行
    yum install nginx -y
    nginx -v

工作流程

  • 1、Nginx 在启动后,会有一个 master 进程和多个相互独立的 worker 进程。
  • 2、接收来自外界的信号,向各worker进程发送信号,每个进程都有可能来处理这个连接。
  • 3、master 进程能监控 worker 进程的运行状态,当 worker 进程退出后(异常情况下),会自动启动新的 worker 进程。
  • worker 进程数,一般会设置成机器 cpu 核数。因为更多的worker 数,只会导致进程相互竞争 cpu,从而带来不必要的上下文切换
  • 使用多进程模式,不仅能提高并发率,而且进程之间相互独立,一个 worker 进程挂了不会影响到其他 worker 进程

安装目录

  • 查看nginx安装的配置文件和目录
rpm -ql nginx

--prefix=/etc/nginx //安装目录
--sbin-path=/usr/sbin/nginx //可执行文件
--modules-path=/usr/lib64/nginx/modules //安装模块
--conf-path=/etc/nginx/nginx.conf  //配置文件路径
--error-log-path=/var/log/nginx/error.log  //错误日志
--http-log-path=/var/log/nginx/access.log  //访问日志
--pid-path=/var/run/nginx.pid //进程ID
--lock-path=/var/run/nginx.lock //加锁对象

nginx 命令

  • 文件配置目录
    • /etc/nginx/nginx.conf
    • /etc/nginx/conf.d/*.conf /etc/nginx/conf.d/default.conf
  • 值指令是向上覆盖的,子配置不存在,可以使用父配置块的指令,如果子指令存在,会覆盖父配置块中的指令

主配置文件

  • /etc/nginx/conf.d/default.conf默认http服务器配置文件
  • /etc/nginx/nginx.conf核心配置文件
# 启动nginx 用户
user nginx;
# work进程数 一般和cpu核数相等
worker_processes auto;
# 错误日志路径
error_log /var/log/nginx/error.log;
# 进程id写入的文件
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
# 事件模块 和node类似  单进程单线程 事件驱动的  注意制作镜像的时候 events要配置 否则会有问题
events {
    # 工作进程的 最大链接数 超过这个就不扔掉了
    # 1024并发量
    # 每个进程允许的最大连接数 10000
    worker_connections 1024;
}
# http配置
http {
    # 定义日志的格式
    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;
    tcp_nodelay         on;
    # 保持连接的超时时间
    keepalive_timeout   65;
    types_hash_max_size 4096;
    # 是否启动gzip压缩
    #gzip               on;

    # 包含mime文件 根据文件后缀 找服务器的相应头 Content-type
    include             /etc/nginx/mime.types;
    # 默认类型 二进制文件
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    # 包含里面的所有文件
    include /etc/nginx/conf.d/*.conf;

    # server 配置服务的
    server {
        listen       80; 
        listen       [::]:80;
        server_name  _;
        root         /usr/share/nginx/html;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

server

  • /etc/nginx/conf.d/default.conf
  • 一个server下面可以配置多个location
# 服务配置 他是最核心的配置文件
server {
    #监听的端口号
    listen       80;  
    #服务名字 后者域名 或者IP
    server_name  localhost;  

    #俄语字符集
    #charset koi8-r; 
    #访问日志文件和名称
    #access_log  /var/log/nginx/host.access.log  main;

    # 重点 location是路径的意思 / 匹配所有
    location / {
        #静态文件根目录
        root   /usr/share/nginx/html;  
        #首页的索引文件
        index  index.html index.htm;  
    }
    # = 代表路径全等 不加等号 则匹配前缀 /a/d能匹配到
    location = /a {
        #静态文件根目录
        root   /usr/share/nginx/html;  
        #首页的索引文件
        index  index.html index.htm;  
    }
    #指定错误页面
    #error_page  404              /404.html;  

    # redirect server error pages to the static page /50x.html
    # 把后台错误重定向到静态的50x.html页面
    error_page   500 502 503 504  /50x.html; 
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

启动和重新加载

  • systemctl restart nginx.service
  • systemctl reload nginx.service
  • nginx -s reload

Jenkins

安装java

  • 安装JDK
// 下载包
wget http://img.zhufengpeixun.cn/jdk1.8.0_211.tar.gz
// 解压包 x解压 z原来是一个gz的包 v显示解压的过程 f指定文件名
tar -xzvf jdk1.8.0_211.tar.gz 
// 将解压的文件 cp 走
cp -r jdk1.8.0_211 /usr/java
// java的执行文件
/use/java/jdk1.8.0_211/bin/java
// 执行查看版本
/use/java/jdk1.8.0_211/bin/java -version 

// 将java执行文件 链接到一个文件 /usr/bin/java 就指代java执行文件
ln -s /use/java/jdk1.8.0_211/bin/java /usr/bin/java

// 配置环境变量  java 就可以在全局访问到了
vi /etc/profile
// 在文件最后加入 下面的 路径根据自己的情况
JAVA_HOME=/usr/java/jdk1.8.0_211
export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
export PATH=$PATH:${JAVA_HOME}/bin

// 使刚才的配置文件生效
source /etc/profile

// 这样全局就可以使用 java了
java -version

安装jenkins

下载

// 1
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
// 2
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key
// 3
yum install jenkins
// 卸载
service jenkins stop
yum clean all
yum -y remove jenkins

// 启动
systemctl start jenkins
// 重启
systemctl restart jenkins
// 查看状态
systemctl status jenkins


// 密码存放位子
/var/lib/jenkins/secrets/initialAdminPassword

// 修改jenkins 默认端口
vim /etc/sysconfig/jenkins
// 找到 JENKINS_PORT="8080" 这个就是默认的8080  将他修改即可 

  • 关闭防火墙
systemctl stop firewalld.service
systemctl disable firewalld.service

jenkins使用

角色和用户管理

  • 安装 Role-based Authorization Strategy 插件

  • 首先注册2个账号分别 zhangsan/lisi

  • 系统管理->Manage Roles 配置管理角色

  • 系统管理->Assign Roles 配置分配角色

  • 新建任务dev-first&&qa-first

  • 新建任务 构建过程加上git,配置如下

  • 有几点要注意

  • 1、jenkins 拉去git代码 需要jenkins 获取ssh公钥,配置到git服务器中

  • 2、修改jenkins配置文件 将用户修改成root,vim /etc/sysconfig/jenkins,修改为JENKINS_USER="root"

  • 3、Repository URL 写git的地址

  • 只要服务器有新的分支 jenkins 就能更新到

安装 Nodejs 环境

  • 我们其实并没有在服务端安装 Node 环境。如果想要安装 Node 环境,有以下两个办法:
    • 源码编译:这种方式是将 Node 源码拉下来后,在服务器端编译完成后才可以使用。时间比较长,流程也略复杂
    • 使用 Jenkins Plugin 中 NodeJS 插件自动配置安装
  • 我们打开 Jenkins 首页,找到左侧的系统配置 => 插件管理 => 可选插件,搜索 Node 。选中 NodeJS 后,点击左下角的 直接安装 开始安装插件
  • 等待安装完毕后,返回 Jenkins 首页。找到 Global Tool Configuration => NodeJS => 新增NodeJS

  • 接着回到 Jenkins 首页,找到左侧的 系统配置 ,选择 全局工具配置

  • 找到下面的 NodeJS ,点击 NodeJS 安装,选择相应的版本填写信息保存即可。

如何使用

  • 那我们在任务中如何使用呢?我们只需要在任务的配置中,找到构建环境,选中 Provide Node & npm bin/ folder to PATH ,选择刚才配置好的 NodeJS 即可。
  • 第一次执行会下载对应的 Node 版本,后续不会下载。

使用 SSH 协议集成 Git 仓库源

  • 这一步,我们使用 Jenkins 集成外部 Git 仓库,实现对真实代码的拉取和构建。在这里,我们选用 Gitee 作为我们的代码源 。这里准备一个 vue-cli 项目来演示构建。

生成公钥私钥

  • 首先,我们先来配置公钥和私钥。这是 Jenkins 访问 Git 私有库的常用认证方式。我们可以使用 ssh-keygen 命令即可生成公钥私钥。在本地机器执行生成即可。这里的邮箱可以换成你自己的邮箱:
ssh-keygen -t rsa -C "xxx@qq.com"
  • 一路回车即可。
  • 结束后,你会得到两个文件。分别是 xxx 和 xxx.pub。
  • 其中,xxx 是私钥文件,xxx.pub 是对应的公钥文件。我们需要在 Git 端配置公钥,在 Jenkins 端使用私钥与 Git 进行身份校验

在 Gitee 配置公钥

  • 在 Gitee 中,如果你要配置公钥有2种方式:仓库公钥 和 个人公钥。其中,如果配置了仓库公钥,则该公钥只能对配置的仓库进行访问。如果配置了个人公钥,则账号下所有私有仓库都可以访问。
  • 这里我们就以配置个人公钥为例子。首先打开右上角的设置 ,点击下面的 安全设置 => SSH公钥
  • 在下方有个添加公钥,填入信息即可。
  • 其中的标题为公钥标题,这里可以自定义标题;公钥则为刚才生成的 xxx.pub 文件。使用 cat 命令查看下文件内容,将内容填入输入框并保存。接着去 Jenkins 端配置私钥

在 Jenkins 配置私钥

  • 回到 Jenkins。在 Jenkins 中,私钥/密码 等认证信息都是以 凭证 的方式管理的,所以可以做到全局都通用。
  • 我们可以在配置任务时,来添加一个自己的凭证。点击项目的 配置,依次找到 源码管理 => Git => Repositories
- 保存后,在 Credentials 下拉列表中选择你添加的凭证。 - 如果没有出现红色无权限提示,则代表身份校验成功,可以正常访问。

构建镜像

编写 DockerFile

  • 基于 nginx:1.15 镜像做底座。
  • 拷贝本地 html 文件夹内的文件,到镜像内 /etc/nginx/html 文件夹。
  • 拷贝本地 conf 文件夹内的文件,到镜像内 /etc/nginx/ 文件夹。
FROM nginx:1.15-alpine
COPY html /etc/nginx/html
COPY conf /etc/nginx/
WORKDIR /etc/nginx/html
  • 编写完成后,怎么生成镜像呢?我们只需要使用 docker build 命令就可以构建一个镜像了:
    • -t: 声明要打一个镜像的Tag标签,紧跟着的后面就是标签。标签格式为 镜像名:版本
docker build -t imagename:version .
  • 因为我们的镜像只包含一个 nginx,所以 dockerfile 内容比较简单。我们只需要在代码根目录下新建一个名为 DockerFile 的文件,输入以下内容,并将其提交到代码库即可。
vi DockerFile
FROM nginx:1.15-alpine
COPY html /etc/nginx/html
COPY conf /etc/nginx/
WORKDIR /etc/nginx/html
git add ./DockerFile
git commit -m "chore: add dockerfile"
git push

Jenkins 端配置

  • 在代码源和 DockerFile 准备就绪后,我们只需在 Jenkins 端配置下要执行的 Shell 脚本即可。找到项目的配置,依次找到 构建 => Execute shell。输入以下脚本:
#!/bin/sh -l

npm install --registry=https://registry.npm.taobao.org
npm run build
docker build -t jenkins-test .
  • 这里脚本很简单,主要就是 安装依赖 => 构建文件 => 构建镜像。填写完毕后保存

Kubernetes

  • 后面才是核心,发现后面东西还有很多,分2次分享