传统的应用开发发布模式
开发团队 在开发环境中完成软件开发,单元测试,测试通过,提交到代码版本管理库。
运维团队 把应用部署到测试环境,供QA团队测试,测试通过后部署生产环境。
QA 团队 purple 进行测试,测试通过后通知部署人员发布到生产环境。
传统发布面临的挑战
错误发现不及时 很多错误在项目的早期可能就存在,到最后集成的时候才发现问题。
人工低级错误发生 产品和服务交付中的关键活动全都需要手动操作。
团队工作效率低 需要等待他人的工作完成后才能进行自己的工作。
开发运维对立 开发人员想要快速更新,运维人员追求稳定,各自的针对的方向不同。
经过上述问题我们需要作出改变,如何改变?
持续集成与持续交付 软件开发的连续方法基于自动执行脚本,以最大程度地减少在开发应用程序时引入错误的机会。从开发新代码到部署新代码,他们几乎不需要人工干预,甚至根本不需要干预。
它涉及到在每次小的迭代中就不断地构建,测试和部署代码更改,从而减少了基于错误或失败的先前版本开发新代码的机会。
此方法有三种主要方法,每种方法都将根据最适合您的策略的方式进行应用。
持续集成(Continuous Integration)
持续合并开发人员正在开发编写的所有代码的一种做法。
通常一天内进行多次合并和提交代码。
从存储库或生产环境中进行构建和自动化测试,以确保没有集成问题并及早发现任何问题。
开发人员提交代码的时候一般先在本地测试验证,只要开发人员提交代码到版本控制系统就会触发一条提交流水线,对本次提交进行验证。
持续交付(Continuous Delivery) 持续交付是超越持续集成的一步。不仅会在推送到代码库的每次代码更改时都进行构建和测试,而且,作为附加步骤,即使部署是手动触发的,它也可以连续部署。此方法可确保自动检查代码,但需要人工干预才能从策略上手动触发更改的部署。
持续部署(Continuous Deployment)
通常可以通过将更改自动推送到发布系统来随时将软件发布到生产环境中。
持续部署会更进一步,并自动将更改推送到生产中。
类似于持续交付,持续部署也是超越持续集成的又一步。不同之处在于,您无需将其手动部署,而是将其设置为自动部署。部署您的应用程序完全不需要人工干预。
CI/CD的价值体现
尽早反馈,尽早发现错误。
减少集成问题,每次发现问题当时解决,避免问题堆积。
每次更改都能成功发布,降低发布风险。
更加频繁的交付价值,客户反馈。
推荐常用的CI/CD工具
Jenkins 专业的CI工具,可扩展自动化服务器、安装配置简单、丰富的插件库、分布式架构设计、支持所有的平台、可视化的管理页面。
GitLab 端到端DevOps工具,常用功能:代码审查、问题跟踪、动态订阅、易于扩展、项目wiki、多角色项目管理、项目代码在线编译预览、CI工具集成。
GitLab CI/CD组件
GitLab CI/CD
GitLab的一部分,GitLab是一个Web应用程序,具有将其状态存储在数据库中的API。
除了GitLab的所有功能之外,它还管理项目/构建并提供一个不错的用户界面。
GitLab Runner
是一个处理构建的应用程序。
可以单独部署,并通过API与GitLab CI / CD一起使用。
.gitlab-ci.yml
定义流水线作业运行,位于应用项目根目录下。
GitLab CI/CD工作原理
将代码托管到Git存储库。
在项目根目录创建ci文件 .gitlab-ci.yml
,在文件中指定构建,测试和部署脚本。
GitLab将检测到它并使用名为GitLab Runner的工具运行脚本。
脚本被分组为作业,它们共同组成了一个管道。
安装GitLabRunner 为什么不是 GitLab CI 来运行那些构建任务? 一般来说,构建任务都会占用很多的系统资源 (譬如编译代码),而 GitLab CI 又是 GitLab 的一部分,如果由 GitLab CI 来运行构建任务的话,在执行构建任务的时候,GitLab 的性能会大幅下降。
GitLab CI 最大的作用是管理各个项目的构建状态,因此,运行构建任务这种浪费资源的事情就交给 GitLab Runner 来做拉! 因为 GitLab Runner 可以安装到不同的机器上,所以在构建任务运行期间并不会影响到 GitLab 的性能
在GNU / Linux上手动安装GitLab Runner
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 如果您不能使用deb/rpm存储库安装GitLab Runner,或者您的GNU / Linux操作系统不在支持的版本中,则可以使用以下一种方法手动安装它,这是最后的选择。 通过deb或rpm软件包 下载软件包 在https://gitlab-runner-downloads.s3.amazonaws.com/latest/index.html上找到最新的文件名和选项 。 选择一个版本并下载二进制文件,如文档所述,该文件用于下载任何其他标记的 GitLab Runner发行版。 例如,对于Debian或Ubuntu: curl -LJO https://gitlab-runner-downloads.s3.amazonaws.com/latest/deb/gitlab-runner_<arch >.deb dpkg -i gitlab-runner_<arch >.deb dpkg -i gitlab-runner_<arch >.deb 例如,对于CentOS或Red Hat Enterprise Linux: curl -LJO https://gitlab-runner-downloads.s3.amazonaws.com/latest/rpm/gitlab-runner_<arch >.rpm rpm -i gitlab-runner_<arch >.rpm rpm -Uvh gitlab-runner_<arch >.rpm
进入GitLab 管理中心 -> 概述 -> Runners页面,获取Gitlab 注册令牌
在gitlab-runner服务器执行命令注册runner
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 [root@gitlab ~] Runtime platform arch =amd64 os=linux pid=22990 revision=e0218c92 version=14.3.2 Running in system-mode. Enter the GitLab instance URL (for example, https://gitlab.com/): http://192.168.1.55/ Enter the registration token: zNSMJ61xg95zVZxKEp5A Enter a description for the runner: [gitlab]: runner001 Enter tags for the runner (comma-separated): runner001 Registering runner... succeeded runner=zNSMJ61x Enter an executor: parallels, ssh, docker+machine, docker-ssh+machine, kubernetes, custom, docker, docker-ssh, shell, virtualbox: docker Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
runner配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 [root@ops177 ~] concurrent = 20 check_interval = 0 [session_server] session_timeout = 1800 [[runners]] name = "ops177" url = "http://192.168.1.55/" token = "B_SUUoftkts1LxfzS8hm" executor = "docker" [runners.custom_build_dir] [runners.cache] [runners.cache.s3] [runners.cache.gcs] [runners.cache.azure] [runners.docker] tls_verify = false image = "registry.cn-shanghai.aliyuncs.com/wikifx/kong:busybox" privileged = false disable_entrypoint_overwrite = false oom_kill_disable = false disable_cache = false volumes = ["/cache" ,"/var/run/docker.sock:/var/run/docker.sock" ] shm_size = 0
刷新页面
持续集成相关的概念 Pipeline 一次 Pipeline 其实相当于一次构建任务,里面可以包含多个流程,如安装依赖、运行测试、编译、部署测试服务器、部署生产服务器等流程。 任何提交或者 Merge Request 的合并都可以触发 Pipeline,如下所示:
1 2 3 4 +------------------+ +----------------+ | | trigger | | | Commit / MR +---------->+ Pipeline | +------------------+ +----------------+
Stages Stages 表示构建阶段,说白了就是上面提到的流程。 我们可以在一次 Pipeline 中定义多个 Stages,这些 Stages 会有以下特点:
所有 Stages 会按照顺序运行,即当一个 Stage 完成后,下一个 Stage 才会开始
只有当所有 Stages 完成后,该构建任务 (Pipeline) 才会成功
如果任何一个 Stage 失败,那么后面的 Stages 不会执行,该构建任务 (Pipeline) 失败
因此,Stages 和 Pipeline 的关系就是:
1 2 3 4 5 6 +--------------------------------------------------------+ | Pipeline | | +-----------+ +------------+ +------------+ | | | Stage 1 |---->| Stage 2 |----->| Stage 3 | | | +-----------+ +------------+ +------------+ | +--------------------------------------------------------+
Jobs Jobs 表示构建工作,表示某个 Stage 里面执行的工作。 我们可以在 Stages 里面定义多个 Jobs,这些 Jobs 会有以下特点:
相同 Stage 中的 Jobs 会并行执行
相同 Stage 中的 Jobs 都执行成功时,该 Stage 才会成功
如果任何一个 Job 失败,那么该 Stage 失败,即该构建任务 (Pipeline) 失败
所以,Jobs 和 Stage 的关系就是:
1 2 3 4 5 6 +------------------------------------------+ | Stage 1 | | +---------+ +---------+ +---------+ | | | Job 1 | | Job 2 | | Job 3 | | | +---------+ +---------+ +---------+ | +------------------------------------------+
gitlab-ci.yml 配置好 Runner 之后,我们要做的事情就是在项目根目录中添加 .gitlab-ci.yml 文件。当我们添加了 .gitlab-ci.yml 文件后,每次提交代码或者合并 MR 都会自动运行构建任务。
Pipeline 是通过提交代码或者合并 MR 来触发的。那么 Pipeline 和 .gitlab-ci.yml 有什么关系呢? 其实 .gitlab-ci.yml 就是拿来在定义 Pipeline 的。
使用GitLab自带的流水线,必须要定义流水线的内容,而定义内容的文件默认叫做.gitlab-ci.yml,使用yml的语法进行编写。 目前任务关键词有28个,全局的关键词有10个,两者重叠的有很多。掌握了这些关键词的用法,可以编写逻辑严谨,易于扩展的流水线。
任务的28个关键词分别是, script, after_script, allow_failure, artifacts, before_script, cache, coverage, dependencies, environment, except, extends, image, include, interruptible, only, pages, parallel, release, resource_group, retry, rules, services, stage, tags, timeout, trigger, variables, when
全局的关键词 image,services,before_script,after_script,tags,cache,artifacts,retry,timeout,interruptible
最常任务中最常用的是这七个script,artifacts,stage, when,tags,image,cache, 下面我先来详细介绍一下这七个关键词,知道了这个七个关键词,一般的流水线随随便便拿下,
gitlab-ci.yml常用关键词
stages 定义管道阶段的名称和顺序。
stage 将指定作业(job)分配给指定stage(阶段)
script 由运行程序执行的 Shell 脚本。[单行/多行]
tags 来选择可用于该项目的runner[project > settings > ci_cd > Runner]
retry 使用retry配置作业多少次失败的情况下重试。
image 指定一个基础Docker镜像作为基础运行环境,经常用到的镜像有node java python docker
only/except 限定当前任务的执行条件,如:只有在指定分区才能被看到
when 实现再发生故障或尽管发生故障时仍能运行的作业
on_success 所有任务执行成功后
on_failure 当至少一个任务失败后
always 执行作业,而不考虑作业在早期阶段的状态。
manual 手动执行任务
delayed 延迟执行任务
never 在rules中不排除执行的任务 在workflow:rules不允许的流水线
cache 是将当前工作环境目录中的一些文件,文件夹等存储起来。用于在各个任务初始化的时候恢复
基本写法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 #自定义阶段 stages: - buildsoft - builddocker - deploy_dev - clear variables: GOPROXY: "https://goproxy.cn" IMAGENAME: "ipinversion" IMAGE: 192.168.200.177/dev_image/ipinversion:${IMAGENAME}_${CI_PIPELINE_ID} SERVICE_NAME: ipinversion NAMESPACE: baseservice NODE_ENV: development buildsoft: stage: buildsoft image: 192.168.200.177/base/golang:latest script: - go build -o ipinversion . - mkdir app/ - cp ipinversion app/ - cp -R conf app/ - cp -R Dockerfile app/ - mkdir -p app/data # tags: # - running01 retry: 2 #重试机制 artifacts: paths: - app/ builddocker: stage: builddocker image: 192.168.200.177/base/dood:latest services: # - name: docker:dind # command: # [ # '--insecure-registry=192.168.200.177', # ] before_script: - echo "$IMGHUBUSER" - echo "$IMGHUBPWD" - docker login 192.168.200.177 -u "$IMGHUBUSER" -p "$IMGHUBPWD" script: - docker build -t ${IMAGE} -f app/Dockerfile app/ - docker push ${IMAGE} after_script: - docker logout ${REGISTRY_URL} dependencies: - buildsoft # tags: # - running01 only: - master # when: # manual deploy_dev: stage: deploy_dev before_script: - mkdir ~/.kube - cat ${KUBE_CONFIG} > ~/.kube/config image: 192.168.200.177/base/kubectl:v1.18.12 script: - cat ${APPLYFILE} > applyfile.yaml - envsubst < applyfile.yaml | kubectl apply -f - # tags: # - running01 only: - master clear: stage: clear script: - rm -rf * - ls -l # tags: # - running01
APPLYFILE发布文件模板变量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 apiVersion: apps/v1 kind: Deployment metadata: name: $SERVICE_NAME namespace: $NAMESPACE spec: replicas: 1 selector: matchLabels: app: $SERVICE_NAME template: metadata: labels: app: $SERVICE_NAME spec: volumes: - name: logsmk hostPath: path: /var/applogs - name: database persistentVolumeClaim: claimName: ipinversionpvc containers: - name: $SERVICE_NAME image: ${IMAGE} imagePullPolicy: IfNotPresent env: - name: ENVIRONMENT valueFrom: configMapKeyRef: name: ipinversion key: ENVIRONMENT ports: - containerPort: 8031 resources: requests: memory: 100Mi cpu: 100m limits: memory: 1024Mi cpu: 1000m livenessProbe: httpGet: path: /get/check port: 8031 scheme: HTTP initialDelaySeconds: 10 periodSeconds: 15 timeoutSeconds: 5 readinessProbe: httpGet: path: /get/check port: 8031 scheme: HTTP initialDelaySeconds: 10 timeoutSeconds: 5 periodSeconds: 15 volumeMounts: - name: logsmk mountPath: /var/applogs/ - name: database mountPath: /app/data/ --- apiVersion: v1 kind: Service metadata: name: $SERVICE_NAME namespace: $NAMESPACE spec: ports: - port: 80 protocol: TCP targetPort: 8031 selector: app: $SERVICE_NAME type: ClusterIP --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: $SERVICE_NAME namespace: $NAMESPACE annotations: nginx.ingress.kubernetes.io/proxy-connect-timeout: "300" nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/proxy-send-timeout: "300" spec: rules: - host: ipinversion.fxeyeinterface.com http: paths: - path: / backend: serviceName: $SERVICE_NAME servicePort: 80
kubectl镜像Dockerfie
1 2 3 4 5 6 7 8 9 10 11 12 [root@node001 kubectl] Dockerfile kubectl [root@node001 kubectl] FROM registry.cn-shanghai.aliyuncs.com/wikifx/base:alpine-glibc-Shanghai MAINTAINER felix ENV TZ "Asia/Shanghai" COPY kubectl /usr/local/bin/ RUN chmod +x /usr/local/bin/kubectl &&\ apk add gettext
更多语法参照:链接
gitlab ci/cd中变量的使用 三种变量的使用
在.gitlab-ci.yml中自己定义
pipeline中预定义的变量
设置在项目中设置变量
变量类型
流水线全局变量
1 2 variables: FELIX: "flask-test"
设置在项目中设置变量
pipeline预定义变量官方文档
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 $ export export CI='true' export CI_API_V4_URL='http://192.168.1.55/api/v4' export CI_BUILDS_DIR='/builds' export CI_BUILD_BEFORE_SHA='0920fb2150639324fc1a3b20639ba7b02f6e1aee' export CI_BUILD_ID='498' export CI_BUILD_MANUAL='true' export CI_BUILD_NAME='deploy' export CI_BUILD_REF='22ce717a8dff73b3abb24ce0e9773e7f0677dbff' export CI_BUILD_REF_NAME='master' export CI_BUILD_REF_SLUG='master' export CI_BUILD_STAGE='deploy' export CI_BUILD_TOKEN='[MASKED]' export CI_COMMIT_AUTHOR='Administrator <admin@example.com>' export CI_COMMIT_BEFORE_SHA='0920fb2150639324fc1a3b20639ba7b02f6e1aee' export CI_COMMIT_BRANCH='master' export CI_COMMIT_DESCRIPTION='' export CI_COMMIT_MESSAGE='Update .gitlab-ci.yml' export CI_COMMIT_REF_NAME='master' export CI_COMMIT_REF_PROTECTED='true' export CI_COMMIT_REF_SLUG='master' export CI_COMMIT_SHA='22ce717a8dff73b3abb24ce0e9773e7f0677dbff' export CI_COMMIT_SHORT_SHA='22ce717a' export CI_COMMIT_TIMESTAMP='2021-10-19T12:25:07+00:00' export CI_COMMIT_TITLE='Update .gitlab-ci.yml' export CI_CONCURRENT_ID='0' export CI_CONCURRENT_PROJECT_ID='0' export CI_CONFIG_PATH='.gitlab-ci.yml' export CI_DEFAULT_BRANCH='master' export CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX='192.168.1.55:80/public-projects/dependency_proxy/containers' export CI_DEPENDENCY_PROXY_PASSWORD='[MASKED]' export CI_DEPENDENCY_PROXY_SERVER='192.168.1.55:80' export CI_DEPENDENCY_PROXY_USER='gitlab-ci-token' export CI_DISPOSABLE_ENVIRONMENT='true' export CI_JOB_ID='498' export CI_JOB_JWT='[MASKED]' export CI_JOB_MANUAL='true' export CI_JOB_NAME='deploy' export CI_JOB_STAGE='deploy' export CI_JOB_STARTED_AT='2021-10-19T12:26:08Z' export CI_JOB_STATUS='running' export CI_JOB_TOKEN='[MASKED]' export CI_JOB_URL='http://192.168.1.55/public-projects/back-end/ip_inversion/-/jobs/498' export CI_NODE_TOTAL='1' export CI_PAGES_DOMAIN='example.com' export CI_PAGES_URL='http://public-projects.example.com/back-end/ip_inversion' export CI_PIPELINE_CREATED_AT='2021-10-19T12:25:08Z' export CI_PIPELINE_ID='71' export CI_PIPELINE_IID='19' export CI_PIPELINE_SOURCE='push' export CI_PIPELINE_URL='http://192.168.1.55/public-projects/back-end/ip_inversion/-/pipelines/71' export CI_PROJECT_DIR='/builds/public-projects/back-end/ip_inversion' export CI_PROJECT_ID='9' export CI_PROJECT_NAME='ip_inversion' export CI_PROJECT_NAMESPACE='public-projects/back-end' export CI_PROJECT_PATH='public-projects/back-end/ip_inversion' export CI_PROJECT_PATH_SLUG='public-projects-back-end-ip-inversion' export CI_PROJECT_REPOSITORY_LANGUAGES='go,dockerfile' export CI_PROJECT_ROOT_NAMESPACE='public-projects' export CI_PROJECT_TITLE='ip反转接口' export CI_PROJECT_URL='http://192.168.1.55/public-projects/back-end/ip_inversion' export CI_PROJECT_VISIBILITY='private' export CI_REGISTRY_PASSWORD='[MASKED]' export CI_REGISTRY_USER='gitlab-ci-token' export CI_REPOSITORY_URL='http://gitlab-ci-token:[MASKED]@192.168.1.55/public-projects/back-end/ip_inversion.git' export CI_RUNNER_DESCRIPTION='running01' export CI_RUNNER_EXECUTABLE_ARCH='linux/amd64' export CI_RUNNER_ID='3' export CI_RUNNER_REVISION='e0218c92' export CI_RUNNER_SHORT_TOKEN='_Q7D-qHB' export CI_RUNNER_TAGS='running01' export CI_RUNNER_VERSION='14.3.2' export CI_SERVER='yes' export CI_SERVER_HOST='192.168.1.55' export CI_SERVER_NAME='GitLab' export CI_SERVER_PORT='80' export CI_SERVER_PROTOCOL='http' export CI_SERVER_REVISION='7fd059d6f16' export CI_SERVER_URL='http://192.168.1.55' export CI_SERVER_VERSION='14.0.4' export CI_SERVER_VERSION_MAJOR='14' export CI_SERVER_VERSION_MINOR='0' export CI_SERVER_VERSION_PATCH='4' export ENV='/root/.bashrc' export FELIX='cakepanit.com' export FF_CMD_DISABLE_DELAYED_ERROR_LEVEL_EXPANSION='false' export FF_DISABLE_UMASK_FOR_DOCKER_EXECUTOR='false' export FF_ENABLE_BASH_EXIT_CODE_CHECK='false' export FF_ENABLE_JOB_CLEANUP='false' export FF_GITLAB_REGISTRY_HELPER_IMAGE='true' export FF_NETWORK_PER_BUILD='false' export FF_SCRIPT_SECTIONS='false' export FF_SKIP_NOOP_BUILD_STAGES='true' export FF_USE_DIRECT_DOWNLOAD='true' export FF_USE_DYNAMIC_TRACE_FORCE_SEND_INTERVAL='false' export FF_USE_FASTZIP='false' export FF_USE_LEGACY_KUBERNETES_EXECUTION_STRATEGY='false' export FF_USE_NEW_BASH_EVAL_STRATEGY='false' export FF_USE_NEW_SHELL_ESCAPE='false' export FF_USE_POWERSHELL_PATH_RESOLVER='false' export FF_USE_WINDOWS_LEGACY_PROCESS_STRATEGY='true' export GITLAB_CI='true' export GITLAB_FEATURES='' export GITLAB_USER_EMAIL='admin@example.com' export GITLAB_USER_ID='1' export GITLAB_USER_LOGIN='root' export GITLAB_USER_NAME='Administrator' export HOME='/root' export HOSTNAME='runner-q7d-qhb-project-9-concurrent-0' export KUBE_CONFIG='/builds/public-projects/back-end/ip_inversion.tmp/KUBE_CONFIG' export NAME='flask-test' export OLDPWD='/' export PATH='/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' export PWD='/builds/public-projects/back-end/ip_inversion' export SHLVL='2'
最终可以实现:
开发提交代码
自动触发流水线构建编译程序
自动打包镜像推入镜像仓库(dood实现)
自动生成k8s yaml文件并自动发布到k8s集群
单仓库多项目扩展写法 如果一个git仓库中存在多个项目。每个目录中存在本项目的dockerfile时。我们应该通过needs
定义流水线中任务的依赖关系。具体写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 stages: - builddocker - deploy_dev variables: WAREHOUSE: 192.168 .200 .177 IMAGE: ${WAREHOUSE}/dev_image/${PROJECT}:${CI_PIPELINE_ID} SERVICE_NAME: ${PROJECT} NAMESPACE: bit .deploy_k8s: &deploy_k8s | cat ${APPLYFILE} > applyfile.yaml envsubst < applyfile.yaml | kubectl apply -f - .init_k8s: &init_k8s | [ -d ~/.kube ] || mkdir ~/.kube cat ${KUBE_CONFIG} > ~/.kube/config .relay: &relay | docker logout ${WAREHOUSE} echo "PROJECT=${PROJECT}" > build.env echo "DOMAIN=${DOMAIN}" >> build.env echo "EXPOSEPORT=${EXPOSEPORT}" >> build.env .build: &docker | docker build -t ${IMAGE} -f ${DOCKER_FILE_PATH} ${CONTEXT_PATH} docker push ${IMAGE} build-bit_survey_web: variables: PROJECT: bit-survey-web DOMAIN: survey.wikibit.com EXPOSEPORT: 8088 DOCKER_FILE_PATH: "trunk/Wikibit.Survey.Web/Dockerfile" CONTEXT_PATH: "trunk/" stage: builddocker image: ${WAREHOUSE}/base/dood:latest before_script: - docker login ${WAREHOUSE} -u "$IMGHUBUSER" -p "$IMGHUBPWD" script: - *docker after_script: - *relay artifacts: reports: dotenv: build.env only: - master when: manual build-bit_live_web: variables: PROJECT: bit-live-web DOMAIN: live.wikibit.com EXPOSEPORT: 8088 DOCKER_FILE_PATH: "trunk/WikibitLive.Web/Dockerfile" CONTEXT_PATH: "trunk/" stage: builddocker image: ${WAREHOUSE}/base/dood:latest before_script: - docker login ${WAREHOUSE} -u "$IMGHUBUSER" -p "$IMGHUBPWD" script: - *docker after_script: - *relay artifacts: reports: dotenv: build.env only: - master when: manual deploy-bit_survey_web: stage: deploy_dev before_script: - *init_k8s image: ${WAREHOUSE}/base/kubectl:v1.18.12 script: - *deploy_k8s needs: - job: build-bit_survey_web artifacts: true only: - master deploy-bit_live_web: stage: deploy_dev before_script: - *init_k8s image: ${WAREHOUSE}/base/kubectl:v1.18.12 script: - *deploy_k8s needs: - job: build-bit_live_web artifacts: true only: - master apiVersion: apps/v1 kind: Deployment metadata: name: ${SERVICE_NAME} namespace: ${NAMESPACE} spec: replicas: 1 selector: matchLabels: app: ${SERVICE_NAME} template: metadata: labels: app: ${SERVICE_NAME} spec: volumes: - name: logsmk hostPath: path: /var/applogs containers: - name: ${SERVICE_NAME} image: ${IMAGE} imagePullPolicy: IfNotPresent env: - name: ENVIRONMENT valueFrom: configMapKeyRef: name: environment key: ENVIRONMENT ports: - containerPort: ${EXPOSEPORT} resources: requests: memory: 100Mi cpu: 100m limits: memory: 1024Mi cpu: 1000m livenessProbe: httpGet: path: /get/check port: ${EXPOSEPORT} scheme: HTTP initialDelaySeconds: 10 periodSeconds: 15 timeoutSeconds: 5 readinessProbe: httpGet: path: /get/check port: ${EXPOSEPORT} scheme: HTTP initialDelaySeconds: 10 timeoutSeconds: 5 periodSeconds: 15 volumeMounts: - name: logsmk mountPath: /var/applogs/ --- apiVersion: v1 kind: Service metadata: name: $SERVICE_NAME namespace: $NAMESPACE spec: ports: - port: 80 protocol: TCP targetPort: ${EXPOSEPORT} selector: app: ${SERVICE_NAME} type: ClusterIP --- apiVersion: extensions/v1beta1 kind: Ingress metadata: name: ${SERVICE_NAME} namespace: ${NAMESPACE} annotations: nginx.ingress.kubernetes.io/proxy-connect-timeout: "300" nginx.ingress.kubernetes.io/proxy-read-timeout: "300" nginx.ingress.kubernetes.io/proxy-send-timeout: "300" spec: rules: - host: ${DOMAIN} http: paths: - path: / backend: serviceName: ${SERVICE_NAME} servicePort: 80
飞书机器人告警 1 2 .remind: &remind | curl -X POST -H 'Content-Type: application/json' --url 'https://open.feishu.cn/open-apis/bot/v2/hook/3cebab07-xxxx-42ce-b5c2-f03d1a7c41ae' -d "{\"msg_type\": \"interactive\",\"card\": {\"config\": {\"wide_screen_mode\": true},\"header\": {\"title\": {\"tag\": \"plain_text\",\"content\": \"DevOps In Testing Environment\"},\"template\": \"blue\"},\"elements\": [{\"tag\": \"markdown\",\"content\": \"**项目名称**:${CI_PROJECT_NAME}/${CI_PROJECT_TITLE} \n**项目地址**:[${CI_PROJECT_URL}](${CI_PROJECT_URL})\n**提交作者**:${CI_COMMIT_AUTHOR} \n**触发作业用户**:${GITLAB_USER_NAME}\n****\n**作业分支**:${CI_COMMIT_BRANCH} \n**CODE SHA**:${CI_COMMIT_SHA}\n**任务ID**:${CI_JOB_ID}\n**任务名称/所处阶段**:${CI_JOB_NAME}/${CI_JOB_STAGE}\n**任务运行详情**:[${CI_JOB_URL}](${CI_JOB_URL}) \n**流水线ID**:${CI_PIPELINE_ID} \n**流水线运行详情**: [${CI_PIPELINE_URL}](${CI_PIPELINE_URL})\"}]} }"
发布静态站点至aliyun OSS 一些静态资源或者vue站点构建出来的h5站点,需要发布在oss上面利用oss的全球加速功能提高访问速度。基于OSS的CICD发布面临挑战。以下是我个人的解决方案 供参考 ossutil支持通过Windows、Linux和macOS系统以命令行方式管理OSS数据。
1 wget http://gosspublic.alicdn.com/ossutil/1.7.7/ossutil64
编写Dockerfile
1 2 3 FROM registry.cn-shanghai.aliyuncs.com/wikifx/base:alpine-glibc-ShanghaiCOPY ossutil64 /bin/ RUN chmod +x /bin/ossutil64
编写.gitlab-ci.yml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 stages: - deploy_oss variables: WAREHOUSE: 192.168.200.177 IMAGE: ${WAREHOUSE} /dev_image/${PROJECT} :${CI_PIPELINE_ID} endPoint: oss-cn-shanghai.aliyuncs.com .deploy_k8s: &deploy_oss | ossutil64 config -e ${endPoint} -i ${accessKeyID} -k ${accessKeySecret} -L CH --loglevel debug -c ~/.ossutilconfig ossutil64 -c ~/.ossutilconfig cp -r -f ./Contentgj/ oss://fxeye-head/Contentgj/ .remind: &remind | curl -X POST -H 'Content-Type: application/json' --url 'https://open.feishu.cn/open-apis/bot/v2/hook/3cebab07-04f7-42ce-b5c2-f03d1a7c41ae' -d "{\"msg_type\": \"interactive\",\"card\": {\"config\": {\"wide_screen_mode\": true},\"header\": {\"title\": {\"tag\": \"plain_text\",\"content\": \"DevOps In Testing Environment\"},\"template\": \"blue\"},\"elements\": [{\"tag\": \"markdown\",\"content\": \"**项目名称**:${CI_PROJECT_NAME} /${CI_PROJECT_TITLE} \n**项目地址**:[${CI_PROJECT_URL} ](${CI_PROJECT_URL} )\n**提交作者**:${CI_COMMIT_AUTHOR} \n**代码版本**:${CI_COMMIT_SHA:0:8} \n**CODE SHA**:${CI_COMMIT_SHA} \n**版本备注**:${CI_COMMIT_MESSAGE} \n****\n**作业分支**:${CI_COMMIT_BRANCH} \n**触发作业用户**:${GITLAB_USER_NAME} \n**任务ID**:${CI_JOB_ID} \n**任务名称/所处阶段**:${CI_JOB_NAME} /${CI_JOB_STAGE} \n**任务运行详情**:[${CI_JOB_URL} ](${CI_JOB_URL} ) \n**流水线ID**:${CI_PIPELINE_ID} \n**流水线运行详情**: [${CI_PIPELINE_URL} ](${CI_PIPELINE_URL} )\"}]} }" deploy_oss-api: stage: deploy_oss before_script: - *remind image: ${WAREHOUSE} /base/ossutil64:1.7.7 script: - *deploy_oss when: manual