生活札记

Docker+K8S+Devops零基础入门教程之Devops

copylian    1 评论    14097 浏览    2023.02.19

DevOpsDevelopmentOperations的组合词)是一组过程、方法与系统的统称,用于促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。

它是一种重视“软件开发人员(Dev)”和“IT运维技术人员(Ops)”之间沟通合作的文化、运动或惯例。透过自动化“软件交付”和“架构变更”的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。

微信图片_20230307100710.png

window系统下go的跨平台编译: CGO_ENABLED=0  GOOS=linux  GOARCH=amd64  go build -o main main.go

教程:https://www.bilibili.com/video/BV1Pt4y1H7Zq

文档: https://pan.baidu.com/s/1LzpsBDVzVK5fZZqMv-0C6Q?pwd=dgu6  提取码: dgu6

安装虚拟机:https://blog.csdn.net/zhiboqingyun/article/details/126555260

虚拟机网卡设置:https://blog.csdn.net/weixin_45193791/article/details/124646170

微信图片_20230309095844.png

    配置IP地址网关

       vi /etc/sysconfig/network-scripts/ifcfg-ens33    //进入到network-scripts目录下  

       //修改以下内容

       BOOTPROTO=static  //启用静态IP地址

       ONBOOT=yes      //开启自动启用网络连接

       //添加vmnet8的子网掩码和网关,ip要保证在192.168.126.x,还要保证唯一性

       IPADDR=192.168.40.100    //设置IP地址

       NETMASK=255.255.255.0   //子网掩码

       GATEWAY=192.168.40.2   //设置网关

                

       设置DNS地址

       vi /etc/resolv.conf    //编辑 resolv.conf文件 

       nameserver 114.114.114.114   //添加DNS地址

       nameserver 8.8.8.8   //添加DNS地址

       

       重启网卡

       systemctl restart network

        

        查看IP是否正常

        ip addr

        ping www.copylian.com

        

        docker安装:https://www.copylian.com/life/503.html

        注意:安装docker之后需要关闭防火墙

        systemctl stop firewalld

        systemctl disable firewalld

        

一、概念:

DevOps,字面意思是Development &Operations的缩写,也就是开发&运维

2021-11-23_175935.png

整体的软件开发流程包括:

PLAN:开发团队根据客户的目标制定开发计划

CODE:根据PLAN开始编码过程,需要将不同版本的代码存储在一个库中。

BUILD:编码完成后,需要将代码构建并且运行。

TEST:成功构建项目后,需要测试代码是否存在BUG或错误。

DEPLOY:代码经过手动测试和自动化测试后,认定代码已经准备好部署并且交给运维团队。

OPERATE:运维团队将代码部署到生产环境中。

MONITOR:项目部署上线后,需要持续的监控产品。

INTEGRATE:然后将监控阶段收到的反馈发送回PLAN阶段,整体反复的流程就是DevOps的核心,即持续集成、持续部署。

        

CI/CD可以理解为:

CI过程即是通过Jenkins将代码拉取、构建、制作镜像交给测试人员测试。

        持续集成:让软件代码可以持续的集成到主干上,并自动构建和测试。

CD过程即是通过Jenkins将打好标签的发行版本代码拉取、构建、制作镜像交给运维人员部署。

        持续交付:让经过持续集成的代码可以进行手动部署。

        持续部署:让可以持续交付的代码随时随地的自动化部署。

image-20211125154112097.png


、Gitlab:GitLab 是一个用于仓库管理系统的开源项目,使用Git作为代码管理工具,并在此基础上搭建起来的Web服务。为了本地测试需要在本地安装下Gitlab仓库。否则可以直接用线上的Gitee

# 拉去仓库镜像,使用docker-compose启动gitlab

docker pull gitlab/gitlab-ce:latest 

mkdir /usr/local/docker/gitlab

cd /usr/local/docker/gitlab

vim docker-compose.yml


        version: '3.1'

        services:

          gitlab:

            image: 'gitlab/gitlab-ce:latest'

            container_name: gitlab

            restart: always

            environment:

              GITLAB_OMNIBUS_CONFIG: |

                external_url 'http://192.168.40.101:8929'

                gitlab_rails['gitlab_shell_ssh_port'] = 2224

            ports:

              - '8929:8929'

              - '2224:2224'

            volumes:

              - './config:/etc/gitlab'

              - './logs:/var/log/gitlab'

              - './data:/var/opt/gitlab'


# 启动容器

docker-compose up -d


# 查看初始密码:

cat /usr/local/docker/gitlab/config/initial_root_password

微信图片_20230308141422.png

# 浏览器访问gitlab,默认账号是root

http://192.168.40.101:8929


# 修改gitlab密码:

微信图片_20230308161657.png

微信图片_20230308161634.png


# 配置允许推送到本地的webhook:admin >> Network

微信图片_20230308143623.png


三、Jenkins:https://www.jenkins.io/

Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,Jenkins应用广泛,大多数互联网公司都采用Jenkins配合GitLabDockerK8s作为实现DevOps的核心工具。Jenkins最强大的就在于插件,Jenkins官方提供了大量的插件库,来自动化CI/CD过程中的各种琐碎功能。Jenkins最主要的工作就是将GitLab上可以构建的工程代码拉取并且进行构建,再根据流程可以选择发布到测试环境或是生产环境。一般是GitLab上的代码经过大量的测试后,确定发行版本,再发布到生产环境。

image-20211125141950900.png

image-20211125141701495.png

1)、安装:使用docker安装,Jenkins目录在 /usr/local/docker/jenkins 

拉去docker镜像:

docker pull jenkins/jenkins:2.375.3-lts 或者 docker pull jenkins/jenkins

        

2)、启动docker-compose:docker-compose up -d 

docker-compose.yml:

        version: "3.1"

        services:

          jenkins:

            image: jenkins/jenkins

            container_name: jenkins

            restart: always

            ports:

               8080:8080

              50000:50000

            volumes:

              ./data/:/var/jenkins_home/

        data作为数据目录映射数据目,需要设置 data 的可写权限chmod -R 777 data/

        

3)、修改Jenkins的镜像,默认国外的下载太慢,配置完成后重启:docker-compose restart jenkins

cat data/hudson.model.UpdateCenter.xml

        <?xml version='1.1' encoding='UTF-8'?>

        <sites>

                <site>

                        <id>default</id>

                        <url>https://updates.jenkins.io/update-center.json</url>

                 </site>

        </sites>

        # 将下载地址替换为http://mirror.esuni.jp/jenkins/updates/update-center.json

         <?xml version='1.1' encoding='UTF-8'?>

        <sites>

                <site>

                        <id>default</id>

                        <url>http://mirror.esuni.jp/jenkins/updates/update-center.json</url>

                 </site>

        </sites>

        # 清华大学的插件源也可以:https://mirrors.tuna.tsinghua.edu.cn/jenkins/updates/update-center.json

        

4)、登录Jenkins:http://192.168.40.101:8080/ 安装插件,相对比较慢要等会。。。

查看密码:

docker logs jenkins -f

docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword

cat data/secrets/initialAdminPassword

        

5)、需要准备的插件或配置:

maven:可通过Jenkins的全局配置安装,也可以自定义下载安装:https://maven.apache.org/download.cgi,下载 apache-maven-4.0.0-alpha-4-bin.tar.gz,解压到Jenkins的jenkins_home下,命名为maven,maven主要是用于java代码打包,如果是其他代码则不需要用到

jdk8可通过Jenkins的全局配置安装,也可以自定义下载安装:https://www.oracle.com/java/technologies/downloads/#java8,下载  jdk-8u361-linux-x64.tar.gz,解压到Jenkins的jenkins_home下,命名为jdk

配置maven镜像、jdk插件,参考:https://blog.csdn.net/m0_67402731/article/details/126435240

vim ./data/maven/conf/setting.xml

                <mirror>

                <id>nexus-aliyun</id>

                <mirrorOf>central</mirrorOf>

                <name>Nexus aliyun</name>

                <url>http://maven.aliyun.com/nexus/content/groups/public/</url>

                </mirror>

        

                <profiles>

                  <profile>    

                    <id>jdk8</id>    

                    <activation>    

                        <activeByDefault>true</activeByDefault>    

                        <jdk>1.8</jdk>    

                    </activation>    

                    <properties>    

                        <maven.compiler.source>1.8</maven.compiler.source>    

                        <maven.compiler.target>1.8</maven.compiler.target>

                        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion> 

                    </properties>    

                    </profile>

                </profiles>

                

                <activeProfiles>

                        <activeProfile>jdk8</activeProfile>

                </activeProfiles>

        

在Jenkins的全局配置里配置:

微信图片_20230228175809.png微信图片_20230228175754.png

Git Parameter:git拉去git仓库上的代码,配置参数

微信图片_20230301133722.png

微信图片_20230301133941.png

微信图片_20230301111628.png

微信图片_20230301133802.png

        

Publish Over SSH:ssh登录服务器

微信图片_20230301132946.png

        

四、SonarQube Scanner代码检测

Sonar Qube在7.9版本中已经放弃了对MySQL的支持,并且建议在商业环境中采用PostgreSQL,那么安装Sonar Qube时需要依赖PostgreSQL。Sonar Qube的使用方式很多,Maven可以整合,也可以采用sonar-scanner的方式,再查看Sonar Qube的检测效果,官网:https://www.sonarsource.com/

Maven方式:修改Maven的settings.xml文件配置Sonar Qube信息

 <profile>
      <id>sonar</id>
      <activation>
          <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
          <sonar.login>admin</sonar.login>
          <sonar.password>123456789</sonar.password>
          <sonar.host.url>http://192.168.11.11:9000</sonar.host.url>
      </properties>
      </profile>

在代码位置执行命令:mvn sonar:sonar


1)、拉取镜像:https://www.sonarsource.com/products/sonarqube/deployment/

docker pull postgres # PostgreSQL镜像

docker pull sonarqube:9.9.0-community

        

2)、docker-compose.yml启动容器:docker-compose up -d

mkdir /usr/local/docker/sonarqube docker-compose.yml 文件位置

        

                version: '3.1'

                services:

                 db:

                  image: postgres

                  container_name: db

                  restart: always

                  ports:

                   - 5432:5432

                  networks:

                   - sonarnet

                  environment:

                    POSTGRES_USER: sonar

                    POSTGRES_PASSWORD: sonar

                

                 sonarqube:

                  image: sonarqube:lts-community

                  container_name: sonarqube

                  restart: always

                  depends_on:

                   - db

                  ports:

                   - 9000:9000

                  networks:

                   - sonarnet

                  environment:

                    SONAR_JDBC_URL: jdbc:postgresql://db:5432/sonar

                    SONAR_JDBC_USERNAME: sonar

                    SONAR_JDBC_PASSWORD: sonar

                

                networks:

                 sonarnet:

                  driver: bridge

        如果报内存不足则需要改配置:vim /etc/sysctl.conf,写入:vm.max_map_count = 262144,sysctl -p查看

        

3)、访问:http://192.168.40.101:9000/,默认账号、密码:admin、admin,安装中文插件生成token并重启

微信图片_20230301152419.png

微信图片_20230301152457.png

        

4)、Jenkins安装SonarQube Scanner for Jenkins插件、系统配置SonarQube服务、下载SonarScanner配置到Jenkins目录、全局配置SonarScanner

        SonarScanner下载:https://docs.sonarqube.org/latest/analyzing-source-code/scanners/sonarscanner/

        cd /usr/local/docker/jenkins/data/ # 切到Jenkins目录

        wget https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.0.2856-linux.zip # 下载

        unzip sonar-scanner-cli-4.8.0.2856-linux.zip # 解压

        mv sonar-scanner-cli-4.8.0.2856-linux/ sonar-scanner # 重命名

        rm -rf sonar-scanner-cli-4.8.0.2856-linux.zip # 删除源文件

        

        测试sonarqube scanner:

        cd /usr/local/devops # 切到代码目录

        /usr/local/docker/jenkins/data/sonar-scanner/bin/sonar-scanner -Dsonar.sources=./ -Dsonar.login=sqa_26b6a9a4f4d860b9b4933da870fa4256c8c2f63d -Dsonar.projectKey=test # 测试

微信图片_20230301154148.png

        

系统配置SonarQube服务:

微信图片_20230301153301.png

全局配置SonarScanner:

微信图片_20230301153222.png

代码重新构建之后:

微信图片_20230301160034.png

微信图片_20230301160007.png

五、Harbor镜像仓库

Harbor是一个开源注册中心,它通过策略和基于角色的访问控制来保护工件,确保图像被扫描并没有漏洞,并将图像签名为可信的。Harbor是一个CNCF Graded项目,它提供了合规性、性能和互操作性,帮助您在Kubernetes和Docker等云原生计算平台上一致、安全地管理工件,官网:https://goharbor.io/

下载:wget https://github.com/goharbor/harbor/releases/download/v2.5.6/harbor-offline-installer-v2.5.6.tgz

解压:tar -zvxf harbor-offline-installer-v2.5.6.tgz -C /usr/local

编辑配置:

cd /usr/local/harbor/

mv harbor.yml.tmpl harbor.yml # 重命名

vim harbor.yml # 配置hostname、http的端口、如果没有https则关闭https配置、默认密码:harbor_admin_password

微信图片_20230302111833.png

        

安装:./install.sh

配置docker的安全镜像:vim /etc/docker/daemon.json

"insecure-registries":["192.168.40.101:80"]

重启docker:systemctl restart docker

微信图片_20230302112741.png

访问:http://192.168.40.101:80,账号密码:admin、Harbor12345,这个仓库一定要是公开的(访问等级是公开的),否则后续k8s或者其他服务器无法拉取镜像

微信图片_20230311115042.png

镜像打标签,并推送到Harbor镜像仓库:

docker tag d44ef6af962c 192.168.40.101:80/test/devops:v1.0.0 # test是新建的仓库名称需要登录先创建

docker login -u admin -p Harbor123456 192.168.40.101:80

docker push 192.168.40.101:80/test/devops:v1.0.0

微信图片_20230302112656.png

微信图片_20230302112854.png

        

配置Jenkins调用外部的docker:

cd /var/run

chown root:root docker.sock # 更改docker.sock的用户组

chmod -R 777 docker.sock # 更改权限

vim /usr/local/docker/jenkins/docker-compose.yml # 编辑jenkins的docker-compose配置

        version: "3.1"

            services:

                jenkins:

                    image: jenkins/jenkins

                    container_name: jenkins

                    restart: always

                    ports:

                        - 8080:8080

                      - 50000:50000

                volumes:

                     - ./data/:/var/jenkins_home/

                     - /usr/bin/docker:/usr/bin/docker

                     - /var/run/docker.sock:/var/run/docker.sock

                     - /etc/docker/daemon.json:/etc/docker/daemon.json

        

进入Jenkins容器内部:docker exec -it jenkins --bash,执行:docker version,能输出docker版本信息则表示Jenkins内部可调用docker

配置Jenkins项目构建时运行docker build、docker push操作:

docker build -t devops:$tag .

docker tag devops:$tag 192.168.40.101:80/test/devops:$tag

docker login -u admin -p Harbor12345 192.168.40.101:80

docker push 192.168.40.101:80/test/devops:$tag

微信图片_20230302135337.png

        

通过shell脚本直接构建镜像、push镜像、拉取镜像、启动容器:docker exec -it jenkins --bash

chmod -R 777 go-build.sh # 给可执行权限

./go-build.sh 192.168.40.101:80 ${JOB_NAME} devops $tag # 执行二级制脚本名,带参数

微信图片_20230303111631.png

微信图片_20230303112459.png

go-build.sh:

# 构建docker镜像、启动镜像

# 镜像仓库地址

repository=$1

        

# 镜像仓库项目名称

repositoryProjectName=$2

        

# 项目名称

projectName=$3

        

# tag名称

tagName=$4

        

# 镜像仓库名称

imageName=$repository/$repositoryProjectName/$projectName

echo $imageName

        

 # 镜像仓库全称

 imageTagName=$imageName:$tagName

 echo $imageTagName

        

# 构建镜像

docker build -t $imageTagName .

        

# 登录仓库

docker login -u admin -p Harbor123456 $repository

        

# 推送仓库

docker push $imageTagName

        

# 查询容器是否在运行,如果存在容器则停止、删除容器

containerId=`docker ps -a | grep ${imageName} | awk '{print $1}'`

echo $containerId

        

if [ "$containerId" != "" ]; then

       docker stop $containerId

       docker rm $containerId

       echo "删除容器成功"

fi

        

# 查询镜像是否存在,如果存在则删除镜像

imageId=`docker images | grep ${imageName} | awk '{print $3}'`

echo $imageId

if [ "$imageId" != "" ]; then

       docker rmi -f $imageId

       echo "删除镜像成功"

fi

        

# 拉取镜像

docker pull $imageTagName

        

#  启动容器

docker run -d --restart=always -p 8081:8081 --name $projectName $imageTagName

echo "启动容器成功"

echo $projectName

微信图片_20230303142733.png

微信图片_20230303142759.png

六、Jenkins流水线:pipeline

Jenkins的Pipeline可以让项目的发布整体流程可视化,明确执行的阶段,可以快速的定位问题。并且整个项目的生命周期可以通过一个Jenkinsfile文件管理,而且Jenkinsfile文件是可以放在项目中维护

Jenkinsfile语法:

                // 所有脚本命令包含在pipeline{}中

                pipeline {

                    // 指定任务在哪个节点执行(Jenkins支持分布式)

                    agent any

                

                    // 配置全局环境,指定变量名=变量值信息

                    environment {

                        host = "192.168.40.101"

                    }

                

                    // 存放所有任务的合集

                    stages {

                        // 单个任务1

                        stage ("任务1") {

                            // 实现任务的具体流程

                            steps {

                                echo "任务1"

                            }

                        }

                

                        // 单个任务2

                        stage ("任务2") {

                            // 实现任务的具体流程

                            steps {

                                echo "任务2"

                            }

                        }

                    }

                }

        

新建Jenkinsfile的流水线任务:

微信图片_20230305222406.png

配置流水线、配置tag:

微信图片_20230305223255.png

微信图片_20230305223231.png

项目目录创建Jenkinsfile:Jenkinsfile的流水线语法Jenkinsfile文件全局配置参数

        // 所有脚本命令包含在pipeline{}中

        pipeline {

            // 指定任务在哪个节点执行(Jenkins支持分布式)

            agent any

        

            // 配置全局环境,指定变量名=变量值信息

            environment {

        

                // 镜像仓库地址

                repository= "192.168.40.101:80"

        

                // 仓库账号

                repositoryUser = "admin"

        

                // 仓库密码

                repositoryPwd = "Harbor12345"

        

                // 项目名称

                projectName = "devops"

        

                // 钉钉ID

                dingRobotId = "Jenkins-Test"

            }

        

            // 存放所有任务的合集

            stages {

                // git版本库拉取代码

                stage ("git版本库拉取代码") {

                    // 实现任务的具体流程

                    steps {

                        checkout scmGit(branches: [[name: '${tag}']], extensions: [], userRemoteConfigs: [[credentialsId: '5a63a5bc-123e-4dde-aa30-48bbb6e9d2a6', url: 'https://gitee.com/copylian/devops.git']])

                    }

                }

        

                // sornar代码检测

                stage ("代码检测") {

                    // 实现任务的具体流程

                    steps {

                        sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.sources=./ -Dsonar.login=sqa_26b6a9a4f4d860b9b4933da870fa4256c8c2f63d'

                    }

                }

        

                // 制作自定义镜像

                stage ("制作Docker自定义镜像") {

                    // 实现任务的具体流程

                    steps {

                        sh 'docker build -t ${repository}/${JOB_NAME}/${projectName}:${tag} .'

                    }

                }

        

                // 推送Docker自定义镜像到Harbor仓库

                stage ("推送Docker自定义镜像到Harbor仓库") {

                    // 实现任务的具体流程

                    steps {

                        sh 'docker login -u ${repositoryUser} -p ${repositoryPwd} ${repository}'

                        sh 'docker push ${repository}/${JOB_NAME}/${projectName}:${tag}'

                    }

                }

        

                // 通过Publish Over SSH通知目标服务器拉取镜像,go-build.sh 拉取

                stage ("通过sh拉取镜像") {

                    // 实现任务的具体流程

                    steps {

                        sh 'chmod -R 777 go-build.sh'

                        sh './go-build.sh ${repository} ${JOB_NAME} ${projectName} ${tag}'

                    }

                }

            }

        

            // 钉钉消息推送

            post {

                success {

                    dingtalk(

                        robot: "${dingRobotId}",

                        type: "MARKDOWN",

                        title: "success:${JOB_NAME}",

                        text: ["- 成功构建:${JOB_NAME}!\n- 版本:${tag}\n 持续时间:${currentBuild.durationString}"]

                    )

                }

        

                failure {

                    dingtalk(

                        robot: "${dingRobotId}",

                        type: "MARKDOWN",

                        title: "success:${JOB_NAME}",

                        text: ["- 成功失败:${JOB_NAME}!\n- 版本:${tag}\n 持续时间:${currentBuild.durationString}"]

                    )

                }

            }

微信图片_20230305224210.png

微信图片_20230305224237.png

微信图片_20230305224301.png


配置钉钉通知:下载DingTalk插件、新建钉钉群聊自定义机器人并全局配置钉钉插件webhook信息、项目选中钉钉、Jenkinsfile的钉钉通知代码、构建通知

微信图片_20230305225211.png

微信图片_20230305223520.png

微信图片_20230305224607.png

微信图片_20230305224622.png

微信图片_20230305223545.png

微信图片_20230305224816.png

微信图片_20230306113030.png

Jenkinsfile的钉钉配置:

        // 钉钉消息推送

            post {

                success {

                    dingtalk(

                        robot: "${dingRobotId}",

                        type: "MARKDOWN",

                        atAll: true,

                        title: "${JOB_NAME}构建成功",

                        text: [

                            "# ${JOB_NAME} ${tag}环境 - 发布成功",

                            "---",

                            "### 构建信息",

                            "",

                            "- 分支: ${tag}",

                            "- 提交: ${env.GIT_COMMIT.take(7)}",

                            "- 时间:${currentBuild.durationString}",

                            "- 日志:[查看详情](${env.BUILD_URL})",

                            "---",

                            "### 更新记录",

                            "",

                            "- 1: ${currentBuild.changeSets}",

                            "- 2: ${currentBuild.description}",

                        ]

                    )

                }

        

                failure {

                    dingtalk(

                        robot: "${dingRobotId}",

                        type: "MARKDOWN",

                        atAll: true,

                        title: "${JOB_NAME}构建失败",

                        text: [

                            "# ${JOB_NAME} ${tag}环境 - 发布失败",

                            "---",

                            "### 构建信息",

                            "",

                            "- 分支: ${tag}",

                            "- 提交: ${env.GIT_COMMIT.take(7)}",

                            "- 时间:${currentBuild.durationString}",

                            "- 日志:[查看详情](${env.BUILD_URL})",

                        ]

                    )

                }

            }

也可配置全局自定义流水线仓库(Global Pipeline Libraries),参考钉钉api

微信图片_20230306123216.png


七、Kubernetes也称为 K8s,是用于自动部署扩缩管理容器化应用程序的开源系统。它将组成应用程序的容器组合成逻辑单元,以便于管理和服务发现。Kubernetes 源自Google 15 年生产环境的运维经验,同时凝聚了社区的最佳创意和实践。官网:https://kubernetes.io/zh-cn/

具体教程参考:https://www.copylian.com/life/504.html

Kubernetes主要能帮助我们完成:

服务发现和负载均衡

Kubernetes 可以使用 DNS 名称或自己的 IP 地址公开容器,如果进入容器的流量很大, Kubernetes 可以负载均衡并分配网络流量,从而使部署稳定。

存储编排

Kubernetes 允许你自动挂载你选择的存储系统,比如本地存储,类似Docker的数据卷。

自动部署和回滚

你可以使用 Kubernetes 描述已部署容器的所需状态,它可以以受控的速率将实际状态 更改为期望状态。Kubernetes 会自动帮你根据情况部署创建新容器,并删除现有容器给新容器提供资源。

自动完成装箱计算

Kubernetes 允许你设置每个容器的资源,比如CPU和内存。

自我修复

Kubernetes 重新启动失败的容器、替换容器、杀死不响应用户定义的容器,并运行状况检查的容器。

秘钥与配置管理

Kubernetes 允许你存储和管理敏感信息,例如密码、OAuth 令牌和 ssh 密钥。你可以在不重建容器镜像的情况下部署和更新密钥和应用程序配置,也无需在堆栈配置中暴露密钥。

微信图片_20230307102131.png

微信图片_20230307102044.png


Kuboard - Kubernetes 多集群管理界面:https://kuboard.cn/

安装Kuboard:https://www.kuboard.cn/install/v3/install-in-k8s.html

kubectl apply -f  https://addons.kuboard.cn/kuboard/kuboard-v3.yaml


1)、Namespace:命名空间:主要是为了对Kubernetes中运行的源进行过隔离, 但是网络是互通的,类似Docker的容器,可以将多个资源配置到一个NameSpace中。而NameSpace可以对不同环境进行资源隔离,默认情况下Kubernetes提供了default命名空间,在构建资源时,如果不指定资源,默认采用default资源。

# 查看现有的全部命名空间

kubectl get ns


# 构建命名空间

kubectl create ns 命名空间名称


# 删除现有命名空间, 并且会删除空间下的全部资源

kubectl delete ns 命名空间名称


yaml文件方式:(构建资源时,设置命名空间)

apiVersion: v1

kind: Namespace

metadata:

        name: test


2)、Pod:Kubernetes运行的一组容器,Pod是Kubernetes的最小单位,但是对于Docker而然,Pod中会运行多个Docker容器

# 查看所有运行的pod

kubectl get pods -A


# 查看指定Namespace下的Pod

kubectl get pod [-n 命名空间]  #(默认default)


# 创建Pod

kubectl run pod名称 --image=镜像名称


# 查看Pod详细信息

kubectl describe pod pod名称


# 删除pod

kubectl delete pod pod名称 [-n 命名空间]  #(默认default)


# 查看pod输出的日志

kubectl logs -f pod名称


# 进去pod容器内部

kubectl exec -it pod名称 -- bash


# 查看kubernetes给Pod分配的ip信息,并且通过ip和容器的端口,可以直接访问

kubectl get pod -owide


yaml方式(推荐)

    apiVersion: v1
            kind: Pod
            metadata:
              labels:
                run: 运行的pod名称
              name: pod名称
              namespace: 命名空间
            spec:
              containers:
              - image: 镜像名称
                name: 容器名称

# 启动Pod:kubectl apply -f yaml文件名称

# 删除Pod:kubectl delete -f yaml文件名称


Pod中运行多个容器:

    apiVersion: v1
          kind: Pod
            metadata:
              labels:
                run: 运行的pod名称
              name: pod名称
              namespace: 命名空间
            spec:
              containers:
              - image: 镜像名称
                name: 容器名称
              - image: 镜像名称
                name: 容器名称
   

3)、Deployment:部署时,可以通过Deployment管理和编排Pod

# 基于Deployment启动容器

kubectl create deployment deployment名称 --image=镜像名称


# 用deployment启动的容器会在被删除后自动再次创建,达到故障漂移的效果

# 需要使用deploy的方式删除deploy

# 查看现在的deployment

kubectl get deployment


# 删除deployment

kubectl delete deployment deployment名称


# 基于Deployment启动容器并设置Pod集群数

kubectl create deployment deployment名称 --image=镜像名称 --replicas 集群个数

  apiVersion: apps/v1
        kind: Deployment
        metadata:
            name: nginx-deployment
            labels:
              app: nginx
          spec:
            replicas: 3
            selector:
              matchLabels:
                app: nginx
            template:
              metadata:
                labels:
                  app: nginx
              spec:
                containers:
                - name: nginx
                 image: nginx
                 ports:
                 - containerPort: 80

正常使用kubectl运行yaml即可


# 基于scale实现弹性伸缩

kubectl scale deploy/Deployment名称 --replicas 集群个数


# 或者修改yaml文件

kubectl edit deploy Deployment名称


#灰度发布

#Deploy可以在部署新版本数据时,成功启动一个pod,才会下线一个老版本的Pod

kubectl set image deployment/Deployment名称 容器名=镜像:版本


4)、Service:可以将多个Pod对外暴露一个Service,让客户端可以通过Service访问到这一组Pod,并且可以实现负载均衡

ClusterIP方式:ClusterIP是集群内部Pod之间的访问方式

# 通过生成service映射一个Deployment下的所有pod中的某一个端口的容器

kubectl expose deployment Deployment名称 --port=Service端口号 --target-port=Pod内容器端口,通过`kubectl get service`查看Service提供的ip,即可访问


NodePort方式:ClusterIP的方式只能在Pod内部实现访问,但是一般需要对外暴露网关,所以需要NodePort的方式Pod外暴露访问

# 通过生成service映射一个Deployment下的所有pod中的某一个端口的容器

kubectl expose deployment Deployment名称 --port=Service端口号 --target-port=Pod内容器端口 --type=NodePort

kubectl expose deployment nginx-deployment --port=8888 --target-port=80 --type=NodePort -n test


容器内部可通过服务名称访问:curl tomcat-deployment:8088

微信图片_20230313152548.png

微信图片_20230313152116.png


Service也可以通过yaml文件实现:
        apiVersion: v1
        kind: Service
        metadata:
          labels
            app: nginx
          name: nginx
          spec:
            selector:
              app: nginx
            ports:
            - port: 8888
             protocol: TCP
             targetPort: 80


通过apply启动就也可以创建Service

测试效果-Deployment部署,通过Service暴露
        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: nginx-deployment
          labels:
            app: nginx-deployment
        spec:
          replicas: 2
          selector:
            matchLabels:
              app: nginx-deployment
          template:
            metadata:
              labels:
                app: nginx-deployment
            spec:
              containers:
              - name: nginx-deployment
                image: nginx
                ports:
                - containerPort: 80
        ---
        apiVersion: v1
        kind: Service
        metadata:
          labels:
            app: nginx-service
          name: nginx-service
        spec:
          selector:
            app: nginx-deployment
          ports:
          - port: 8888
            protocol: TCP
            targetPort: 80
          type: NodePort


5)、Ingress:Kubernetes推荐将Ingress作为所有Service的入口,提供统一的入口,避免多个服务之间需要记录大量的IP或者域名,毕竟IP可能改变,服务太多域名记录不方便。Ingress底层其实就是一个Nginx, 可以在Kuboard上直接点击安装,因为副本数默认为1,但是k8s整体集群就2个节点,所以显示下面即为安装成功,可以将Ingress接收到的请求转发到不同的Service中。

推荐使用yaml文件方式
        apiVersion: networking.k8s.io/v1
        kind: Ingress
        metadata:
          name: nginx-ingress
        spec:
          ingressClassName: ingress # 这个ingress需要安装
          rules:
          - host: te.abc.com
            http:
              paths:
              - path: /
                pathType: Prefix
                backend:
                  service:
                    name: nginx-service
                    port:
                      number: 8888

配置本地hosts文件:1270.0.01test.abc.com


八、Jenkins集成Kubernetes镜像构建成功之后推送到仓库之后,将k8s的yaml部署文件推送到k8s主机,远程执行k8s的配置文件(包括重新加载rollout

1)、k8s的master节点、node节点需要docker拉去私服镜像的权限

k8s所有节点都得配置:

vim /etc/docker/daemon.json


添加私服仓库:这个仓库一定要是公开的(访问等级是公开的),否则一直报没有拉取镜像的权限,重要事情说一遍

"insecure-registries":["192.168.40.101:80"]

微信图片_20230311115049.png


重启docker

systemctl daemon-reload

systemctl restart docker


测试拉取镜像:docker pull 192.168.40.101:80/test2/devops:v3.0.0

微信图片_20230307225743.png


2)、配置Jenkins(容器内部)登录k8s主机,通过Publish over SSH传输对应的yaml文件

Jinkens主机:

        docker exec -it jenkins bash

        cd ~/.ssh # 如果没有.ssh则直接生成,参考:https://blog.csdn.net/qq_55624813/article/details/121385737

        cat id_rsa.pub # 复制id_rsa.pub内容到k8s主机


k8s主机:

        将内容写入k8s主机文件中:

        vim  ~/.ssh/authorized_keys


直接在Jenkins内部测试:ssh root@192.168.40.201


Jenkins系统配置中配置Publish over SSH:生成Jenkinsfile语法将文件传输过去

微信图片_20230307223934.png

微信图片_20230307224258.png

远程目录 /usr/local/k8s 需要先创建,否则会报权限问题

配置Jenkinsfile文件:

// 通过Publish Over SSH将部k8smaster.yaml署到k8smaster机器

        stage ("将部k8smaster.yaml署到k8smaster机器") {

            // 实现任务的具体流程

            steps {

                sshPublisher(publishers: [sshPublisherDesc(configName: 'k8smaster', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'k8smaster.yaml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

            }

        }


3)、远程执行yaml文件:重启k8s应用、部署应用

微信图片_20230308111250.png

配置Jenkinsfile文件:

// 远程执行k8smaster.yaml文件

        stage ("远程执行k8smaster.yaml文件") {

            // 实现任务的具体流程

            steps {

                sh '''ssh root@192.168.40.201 kubectl apply -f /usr/local/k8s/k8smaster.yaml

                ssh root@192.168.40.201 kubectl rollout restart deployment devops -n test'''

            }

        }


4)、为了本地测试开启gitlab的本地webhook,并配置webhook来实现推送就触发Jenkins流水进程

下载gitlab插件:

微信图片_20230308162646.png


项目配置gitlab流水线信息:

微信图片_20230308163018.png


配置gitlab的webhook:

微信图片_20230308162931.png

微信图片_20230308162945.png

微信图片_20230308163122.png


项目构建:

微信图片_20230308113303.png


访问项目:http://192.168.40.201:32270/test,环境问题无法配置ingress,所以暂时只能通过ip+端口访问,如果加了ingress方式那可以配置本机hosts文件来直接访问

微信图片_20230308164319.png


九、Kuboard - Kubernetes 多集群管理界面:https://www.kuboard.cn/

安装:https://www.kuboard.cn/install/v3/install-in-k8s.html

微信图片_20230311191032.png

选择华为云的镜像安装,推荐的镜像很慢,可能会一直安装不上,安装完成之后按照文档操作登录即可。

微信图片_20230311191349.png


十、pipeline整体关键性文件:包含Dockerfile构建镜像文件、go-build.sh 脚本文件、Jenkinsfile 流水线文件、k8s的yaml配置文件

Dockfile:容器内部

    FROM alpine:latest

    WORKDIR /usr/local/devops

    COPY ./main /usr/local/devops/main

    RUN chmod -R 777 /usr/local/devops/main

    EXPOSE 8081

    CMD [ "./main" ]


go-build.sh:./go-build.sh 192.168.40.101 test devops latest

    # 构建docker镜像、启动镜像

    # 镜像仓库地址

    repository=$1

    

    # 镜像仓库项目名称

    repositoryProjectName=$2

    

    # 项目名称

    projectName=$3

    

    # tag名称

    tagName=$4

    

    # 镜像仓库名称

    imageName=$repository/$repositoryProjectName/$projectName

    echo $imageName

    

    # 镜像仓库全称

   imageTagName=$imageName:$tagName

   echo $imageTagName

    

    # 查询容器是否在运行,如果存在容器则停止、删除容器

    containerId=`docker ps -a | grep ${imageName} | awk '{print $1}'`

    echo $containerId

    if [ "$containerId" != "" ]; then

        docker stop $containerId

        docker rm $containerId

        echo "删除容器成功"

    fi

    

    # 查询镜像是否存在,如果存在则删除镜像

    imageId=`docker images | grep ${imageName} | awk '{print $3}'`

    echo $imageId

    if [ "$imageId" != "" ]; then

        docker rmi -f $imageId

        echo "删除镜像成功"

    fi

    

Jenkinsfile:用于pipeline

// 所有脚本命令包含在pipeline{}中

pipeline {

            // 指定任务在哪个节点执行(Jenkins支持分布式)

            agent any

        

            // 配置全局环境,指定变量名=变量值信息

            environment {

        

                // 镜像仓库地址

                repository= "192.168.40.101:80"

        

                // 仓库账号

                repositoryUser = "admin"

        

                // 仓库密码

                repositoryPwd = "Harbor12345"

        

                // 项目名称

                projectName = "devops"

        

                // 钉钉ID

                dingRobotId = "Jenkins-Test"

            }

        

            // 存放所有任务的合集

            stages {

                // git版本库拉取代码

                stage ("git版本库拉取代码") {

                    // 实现任务的具体流程

                    steps {

                        checkout scmGit(branches: [[name: '*/master']], extensions: [], userRemoteConfigs: [[credentialsId: 'b8c8ed01-15d8-4bfd-afd2-8dddfd0623bb', url: 'http://192.168.40.101:8929/test/devops3.git']])

                    }

                }

        

                // 代码检测

                stage ("代码检测") {

                    // 实现任务的具体流程

                    steps {

                        sh '/var/jenkins_home/sonar-scanner/bin/sonar-scanner -Dsonar.projectname=${JOB_NAME} -Dsonar.projectKey=${JOB_NAME} -Dsonar.sources=./ -Dsonar.login=sqa_26b6a9a4f4d860b9b4933da870fa4256c8c2f63d'

                    }

                }

        

                // 删除不用的镜像

                stage ("删除不用的镜像") {

                    // 实现任务的具体流程

                    steps {

                        sh 'chmod -R 777 go-build.sh'

                        sh './go-build.sh ${repository} ${JOB_NAME} ${projectName} latest'

                    }

                }

        

                // 制作自定义镜像

                stage ("制作Docker自定义镜像") {

                    // 实现任务的具体流程

                    steps {

                        sh 'docker build -t ${repository}/${JOB_NAME}/${projectName}:latest .'

                    }

                }

        

                // 推送Docker自定义镜像到Harbor仓库

                stage ("推送Docker自定义镜像到Harbor仓库") {

                    // 实现任务的具体流程

                    steps {

                        sh 'docker login -u ${repositoryUser} -p ${repositoryPwd} ${repository}'

                        sh 'docker push ${repository}/${JOB_NAME}/${projectName}:latest'

                    }

                }

        

                // 通过Publish Over SSH将部k8smaster.yaml署到k8smaster机器

                stage ("将部k8smaster.yaml署到k8smaster机器") {

                    // 实现任务的具体流程

                    steps {

                        sshPublisher(publishers: [sshPublisherDesc(configName: 'k8smaster', transfers: [sshTransfer(cleanRemote: false, excludes: '', execCommand: '', execTimeout: 120000, flatten: false, makeEmptyDirs: false, noDefaultExcludes: false, patternSeparator: '[, ]+', remoteDirectory: '', remoteDirectorySDF: false, removePrefix: '', sourceFiles: 'k8smaster.yaml')], usePromotionTimestamp: false, useWorkspaceInPromotion: false, verbose: false)])

                    }

                }

        

                // 远程执行k8smaster.yaml文件,重启应用

                stage ("远程执行k8smaster.yaml文件,重启应用") {

                    // 实现任务的具体流程

                    steps {

                        sh '''ssh root@192.168.40.201 kubectl apply -f /usr/local/k8s/k8smaster.yaml

                        ssh root@192.168.40.201 kubectl rollout restart deployment devops -n test'''

                    }

                }

            }

        

            // 钉钉消息推送

            post {

                success {

                    dingtalk(

                        robot: "${dingRobotId}",

                        type: "MARKDOWN",

                        atAll: true,

                        title: "${JOB_NAME}构建成功",

                        text: [

                            "# ${JOB_NAME} 环境 - 发布成功",

                            "---",

                            "### 构建信息",

                            "",

                            "- 分支: latest",

                            "- 提交: ${env.GIT_COMMIT.take(7)}",

                            "- 时间:${currentBuild.durationString}",

                            "- 日志:[查看详情](${env.BUILD_URL})",

                            "---",

                            "### 更新记录",

                            "",

                            "- 1: ${currentBuild.changeSets}",

                            "- 2: ${currentBuild.description}",

                        ]

                    )

                }

        

                failure {

                    dingtalk(

                        robot: "${dingRobotId}",

                        type: "MARKDOWN",

                        atAll: true,

                        title: "${JOB_NAME}构建失败",

                        text: [

                            "# ${JOB_NAME} 环境 - 发布失败",

                            "---",

                            "### 构建信息",

                            "",

                            "- 分支: latest",

                            "- 提交: ${env.GIT_COMMIT.take(7)}",

                            "- 时间:${currentBuild.durationString}",

                            "- 日志:[查看详情](${env.BUILD_URL})",

                        ]

                    )

                }

            }

}


k8s的yaml配置文件:

        apiVersion: apps/v1

        kind: Deployment

        metadata:

          namespace: test

          name: devops

          labels:

            app: devops

        spec:

          replicas: 2

          selector:

            matchLabels:

              app: devops

          template:

            metadata:

              labels:

                app: devops

            spec:

              containers:

                - name: devops

                  image: 192.168.40.101:80/test2/devops:latest

                  imagePullPolicy: Always

                  ports:

                    - containerPort: 8081

        ---

        apiVersion: v1

        kind: Service

        metadata:

          namespace: test

          labels:

            app: devops

          name: devops

        spec:

          selector:

            app: devops

          ports:

            - port: 8082

              targetPort: 8081

          type: NodePort

        ---

        # 如果环境支持ingress的话可以配置ingress

        apiVersion: networking.k8s.io/v1

        kind: Ingress

        metadata:

          namespace: test

          name: devops

        spec:

          ingressClassName: ingress # 这个ingress需要安装

          rules:

          - host: test.devops..com

            http:

              paths:

              - path: /

                pathType: Prefix

                backend:

                  service:

                    name: devops

                    port:

                      number: 8082


配置host指向:C:\Windows\System32\drivers\etc\hosts

微信图片_20230311171428.png

微信图片_20230311171509.png


十一、腾讯CODING DevOps:https://console.cloud.tencent.com/coding/container-devops

CODING DevOps 面向容器业务场景,提供代码编译、容器镜像构建、镜像推送及应用部署等功能,与容器服务 TKE、容器镜像服务 TCR 紧密结合,共同提供强大的云原生 DevOps 服务。

微信图片_20230219223104.png


只袄早~~~
感谢你的支持,我会继续努力!
扫码打赏,感谢您的支持!
Docker K8S Devops jenkins 

文明上网理性发言!