Ubuntu google java wordpress Android centos 程序员 mysql linux Windows php 云计算 微软 Python Firefox 开源 编程 nginx apache shell

超實用:小團隊如何從零搭建一個自動化運維體系?

如下圖,現在行業內各巨頭自動化運維架構的最終樣子大家都知道了,但是如何根據自己團隊當前的情況一步步向這個目標演進?

筆者所在團隊,三個半開發,要維護幾十臺雲機器,部署了十來個應用,這些應用 90% 都是遺留系統。

應用系統的編譯打包基本在程序員自己的電腦上。分支管理也清一色的 dev 分支開發,測試通過後,再合並到 master 分支。

生產環境的應用配置要登錄上具體的機器看才知道,更不用說配置中心及配置版本化了。對了,連基本的機器級別的基礎監控都沒有。

我平時的工作是 50% 業務開發,50% 運維。面對這麽多問題,我就想,如何在低成本情況下實現自動化運維。

本文就是總結我在這方面一些經驗和實踐,希望對讀者有幫助。

別說話,先上監控和告警

事情有輕重緩急,監控和告警是我覺得一開始就要做的,即使業務開發被拖慢。只有知道了當前的情況,你才好做下一步計劃。

現在市面上監控系統很多:Zabbix、Open-Falcon、Prometheus,但是最終我選擇了 Prometheus。

原因有如下幾點:

它是拉模式的。
它方便使用文本方式來配置,有利於配置版本化。
插件多,想要監控什麽,基本都會有現成的插件。
以上三者,我基本都要重新學,我為什麽不學一個 Google SRE 書上推薦的呢?

之前我們已經介紹過,人少機器多,所以安裝 Prometheus 的過程也必須要自動化,同時版本化。我使用的是 Ansible + Git 實現。

最終樣子如下:

这里需要简单介绍一下:

  • Prometheus Server 负责监控数据收集和存储。
  • Prometheus Alert manager 负责根据告警规则进行告警,可集成很多告警通道。
  • node-exporter[1] 的作用就是从机器读取指标,然后暴露一个 http 服务,Prometheus 就是从这个服务中收集监控指标。当然 Prometheus 官方还有各种各样的 exporter。

使用 Ansible 作为部署工具的一个好处是太多现成的 role 了,安装 Prometheus 时,我使用的是现成的:prometheus-ansble[2]。

有了监控数据后,我们就可以对数据进行可视化,Grafana 和 Prometheus 集成得非常好,所以我们又部署了 Grafana:

在 Grafana 上查看 nodex-exporter 收集的数据的效果图大概如下:

可是,我们不可能 24 小时盯着屏幕看 CPU 负载有没有超吧?这时候就要上告警了,Promehtues 默认集成了 N 多告警渠道,可惜没有集成钉钉。

但也没有关系,有好心的同学开源了钉钉集成 Prometheus 告警的组件:prometheus-webhook-dingtalk[3]。

接着,我们告警也上了:

完成以上工作后,我们基础监控的架子就完成了,这为我们后期上 Redis 监控、JVM 监控等更上层的监控做好了准备。

配置版本化要从娃娃抓起

在搭建监控系统的过程中,我们已经将配置抽离出来,放到一个单独的代码仓库进行管理。以后所有部署,我们都会将配置和部署逻辑分离。

关于如何使用 Ansible 进行配置管理,可以参考这篇文章:How to Manage Multistage Environments with Ansible[4] 。

我们就是使用这种方式来组织环境变量的。


 
  1. ├── environments/         # Parent directory for our environment-specific directories 
  2. │   │ 
  3. │   ├── dev/              # Contains all files specific to the dev environment 
  4. │   │   ├── group_vars/   # dev specific group_vars files 
  5. │   │   │   ├── all 
  6. │   │   │   ├── db 
  7. │   │   │   └── web 
  8. │   │   └── hosts         # Contains only the hosts in the dev environment 
  9. │   │ 
  10. │   ├── prod/             # Contains all files specific to the prod environment 
  11. │   │   ├── group_vars/   # prod specific group_vars files 
  12. │   │   │   ├── all 
  13. │   │   │   ├── db 
  14. │   │   │   └── web 
  15. │   │   └── hosts         # Contains only the hosts in the prod environment 
  16. │   │ 
  17. │   └── stage/            # Contains all files specific to the stage environment 
  18. │       ├── group_vars/   # stage specific group_vars files 
  19. │       │   ├── all 
  20. │       │   ├── db 
  21. │       │   └── web 
  22. │       └── hosts         # Contains only the hosts in the stage environment 
  23. │ 

现阶段,我们所有的配置都以文本的方式存储,将来要切换成使用 Consul 做配置中心,也非常的方便,因为 Ansible 2.0 以上的版本已经原生集成了Consul:consul_module[5]。

Tips:Ansible 的配置变量是有层次的,这为我们的配置管理提供了非常大的灵活性。

Jenkins 化:将打包交给 Jenkins

我们要将所有项目的打包工作交给 Jenkins。当然,现实中我们是先将一些项目放到 Jenkins 上打包,然后逐步将项目放上 Jenkins。

首先我们要有 Jenkins,搭建 Jenkins 同样有现成的 Ansible 脚本:ansible-role-jenkins[6]。

注意了,在网上看到的大多文章告诉你 Jenkins 都是需要手工安装插件的,而我们使用的这个 ansible-role-jenkins 实现了自动安装插件,你只需要加一个配置变量 jenkins_plugins 就可以了。

官方例子如下:


 
  1. --- 
  2. - hosts: all 
  3.   vars: 
  4.     jenkins_plugins: 
  5.       - blueocean 
  6.       - ghprb 
  7.       - greenballs 
  8.       - workflow-aggregator 
  9.     jenkins_plugin_timeout: 120 
  10.   pre_tasks: 
  11.     - include_tasks: JAVA-8.yml 
  12.   roles: 
  13.     - geerlingguy.java 
  14.     - ansible-role-jenkins 

搭建好 Jenkins 后,就要集成 Gitlab 了。我们原来就有 Gitlab ,所以不需要重新搭建。

最终 Jenkins 搭建成以下这个样子:

关于 Jenkins master 与 Jenkins agent 的连接方式,由于网络环境各不相同,网上也有很多种方式,大家自行选择适合的方式。

现在我们需要告诉 Jenkins 如何对我们的业务代码进行编译打包,有两种方法:

界面上设置

  • 使用 Jenkinsfile:类似于 Dockerfile 的一种文本文件,具体介绍:Using a Jenkinsfile[7]
  • 我毫不犹豫地选择了第二种,因为一是利于版本化;二是灵活。

Jenkinsfile 类似这样:


 
  1. pipeline { 
  2.     agent any 
  3.     stages { 
  4.         stage('Build') { 
  5.             steps { 
  6.                 sh './gradlew clean build' 
  7.                 archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true 
  8.             } 
  9.         } 
  10.     } 

那么 Jenkinsfile 放哪里呢?答案是和业务代码放在一起,类似这样每个工程各自管理自己的 Jenkinsfile:

這時,我們就可以在 Jenkins 上創建一個 pipleline Job了。關於分支管理,我們人少,所以,建議所有項目統一在 master 分支進行開發並發布。

讓 Jenkins 幫助我們執行 Ansible

之前我們都是在程序員的電腦執行 Ansible 的,現在我們要把這項工作交給 Jenkins。

具體操作:

在 Jenkins 安裝 Ansible 插件[8]
在 Jenkinsfile 中執行

withCredentials([sshUserPrivateKey(keyFileVariable:"deploy_private",credentialsId:"deploy"),file(credentialsId: 'vault_password', variable: 'vault_password')]) { 
             ansiblePlaybook vaultCredentialsId: 'vault_password', inventory: "environments/prod", playbook: "playbook.yaml", 
             extraVars:[ 
               ansible_ssh_private_key_file: [value: "${deploy_private}", hidden: true], 
               build_number: [value: "${params.build_number}", hidden: false] 
             ] 

這裏需要解釋下:

ansiblePlaybook 是 Jenkins ansible 插件提供的 pipeline 語法,類似手工執行:ansible-playbook 。
withCredentials 是 Credentials Binding[9] 插件的語法,用於引用一些敏感信息,比如執行 Ansible 時需要的 ssh key 及 Ansible Vault 密碼。
一些敏感配置變量,我們使用 Ansible Vault[10] 技術加密。
Ansible 腳本應該放哪?

我們已經知道各個項目各自負責自己的自動化構建,所以 Jenkinfile 就放到各自項目中。

那項目的部署呢?同樣的道理,我們覺得也應該由各個項目自行負責,所以我們的每個要進行部署的項目下都會有一個 Ansible 目錄,用於存放 Ansible 腳本。

類似這樣:

但是,怎麽用呢?我們會在打包階段將 Ansible 目錄進行 zip 打包,到真正部署時,再解壓執行裏面的 playbook。

快速為所有的項目生成 Ansible 腳本及Jenkinsfile

上面,我們將一個項目進行 Jenkins 化和 Ansible 化,但是我們還有很多項目需要進行同樣的動作。

考慮到這是體力活,而且以後我們還會經常做這樣事,所以我決定使用 cookiecutter[11] 技術自動生成 Jenkinsfile 及 Ansible 腳本,創建一個項目,像這樣:

小結

總結下來,我們小團隊的自動化運維實施的順序大概為:

上基礎監控
上 Gitlab
上 Jenkins,並集成 Gitlab
使用 Jenkins 實現自動編譯打包
使用 Jenkins 執行 Ansible
以上只是一個架子,基於這個“架子”,就可以向那些大廠高大上的架構進行演進了,比如:

CMDB 的建設:我們使用 ansible-cmdb[12] 根據 inventory 自動生成當前所有機器的情況。
發布管理:Jenkins 上可以對發布的每個階段進行定制。藍綠發布等發布方式可以通過修改 Ansible 腳本和 Inventory 實現。
自動擴縮容:通過配置 Prometheus 告警規則,調用相應 webhook 就可以實現。
ChatOps:ChatOps 實戰[13]。
以上就是我關於自動化運維的一些實踐,但是還在演進的路上,希望能與大家交流。

相關鏈接:

  • [1]https://github.com/prometheus/node_exporter
  • [2]https://github.com/ernestas-poskus/ansible-prometheus
  • [3]https://github.com/timonwong/prometheus-webhook-dingtalk
  • [4]https://www.digitalocean.com/community/tutorials/how-to-manage-multistage-environments-with-ansible
  • [5]http://docs.ansible.com/ansible/latest/modules/consul_module.html
  • [6]https://github.com/geerlingguy/ansible-role-jenkins
  • [7]https://jenkins.io/doc/book/pipeline/jenkinsfile/
  • [8]https://wiki.jenkins.io/display/JENKINS/Ansible+Plugin
  • [9]https://jenkins.io/doc/pipeline/steps/credentials-binding/
  • [10]http://docs.ansible.com/ansible/2.5/user_guide/vault.html
  • [11]https://github.com/audreyr/cookiecutter
  • [12]https://github.com/fboender/ansible-cmdb
  • [13]https://showme.codes/2017-10-08/chatops-in-action/

延伸阅读

    评论