IT運維,指的是對已經搭建好的網絡、軟件、硬件進行維護。運維領域也是細分的,有硬件運維和軟件運維。html
硬件運維主要包括對基礎設施的運維,例如機房的設備,主機的鍵盤,內存等物理設備的維護。web
軟件運維主要包括系統運維和應用運維,系統運維主要包括對OS,數據庫,中間件的監控和維護,這些系統介於設備和應用之間,應用運維主要是對線上業務系統的運維。shell
這裏主要討論的是軟件運維的自動化,包括系統運維和應用運維的自動化。數據庫
平常運維工做繁瑣,研發會常常須要到服務器上查看日誌,重啓應用,或者是上線某個產品須要部署環境等,都是運維的平常。django
在部署某個應用後,應用不能訪問,在開發環境運行的好,可是在測試環境後就不能繼續用了,由於各種環境的類庫不統一。還有一種狀況是,因爲運維人員的習慣不一樣,按照本身的習慣來安裝部署環境,每種服務器上運行的軟件目錄不統一。服務器
運維人員須要登陸到服務器上執行命令,部署程序,不只效率低,而且很是容易出現人爲錯誤,人爲出錯以後也不容易找到問題所在。網絡
運維人員常常會收到不少的無用報警信息,經常會選擇屏蔽這些報警信息,而且一旦應用的訪問速度出了問題,就須要從系統、網絡、應用、數據庫等一步步查找信息。app
資產管理,服務管理常常記錄在Excel或者文本里面,不便於管理。老員工因爲熟悉不注重文檔的維護,新員工入職時,資產才能更正一次。運維
流程:產品經理調研(畫出原型圖)-->定需求-->三方會談(研發,產品經理,老大們)-->定日期-->測試項目-->最終上線-->應用運維dom
目前:將代碼打包給運維,運維解壓上線
問題:隨着機器數量的線性增長,運維的工做量也是線性增長,重複並且是毫無心義的勞動
解決:
1:寫一個shell腳本,進行部署
2:搞一個自動化代碼上線系統
必要條件:服務器的各類信息(主機名,CPU,硬盤大小等)
監測服務器的各類信息(硬盤是否滿,CPU的使用率,內存使用率,網站服務運行是否正常)
問題:以前簡單的腳本,監測服務器的信息,比較麻煩
解決:想將服務器的各類信息,以圖表的形式展現在web界面上(可視化)
必要條件:服務器的各類信息(主機名,CPU,硬盤大小等)
問題:人工裝機須要一臺一臺去裝
解決:搞一個裝機系統,cobbler軟件
必要條件:服務器的各類信息(主機名,CPU等)
1:用戶管理,記錄測試,開發,運維人員的用戶表
2:業務線管理,須要記錄業務的詳情
3:項目管理,指定此項目需屬於那條業務線,以及項目詳情
4:應用管理,指定此應用的開發人員,屬於哪一個項目,和代碼地址,部署目錄,部署集羣,依賴的應用,軟件等信息。
5:主機管理,包括雲主機,物理機,主機屬於哪一個集羣,運行着哪些軟件,主機管理員,鏈接着哪些網絡設備,雲主機的資源地,存儲等相關信息。
6:主機變動管理,主機的一些信息變動,例如管理員,所屬集羣等信息更改,鏈接的網絡變動等。
7:網絡設備管理,主要記錄網絡設備的詳細信息,及網絡設備鏈接的上級設備
8:IP管理,IP屬於哪一個主機,哪一個網段,是否被佔用等
能夠將服務器上面的Agent程序做定時任務,定時將資產信息提交到指定API錄入數據庫
本質就是在各個服務器上執行subprocess.getoutput("命令"),而後將每臺機器上執行的結果返回給主句API,而後主機API收到這些數據以後,放到數據庫中,最終經過web界面展示給用戶。 優勢:速度快 缺點:須要爲每臺服務器部署有關Agent程序
使用場景:服務器比較多的時候
中控機經過Paramiko(py模塊)登陸到各個服務器上,而後執行命令的方式去獲取各個服務器上的信息。
優勢:沒有Agent
缺點:有一箇中控機,速度慢
使用場景:服務器比較少的時候
此方案本質上和第二種方案是差很少的流程,中控機發送命令給服務器執行。服務器將結果放入另外一個隊列中,中控機獲取將服務信息發送到API進而錄入到數據庫。
優勢:速度快,開發成本低
缺點:依賴於第三方工具
使用場景:公司已經使用salt-stack軟件
saltstack的安裝和配置
1:安裝和配置
master端: """ 1. 安裝salt-master yum install salt-master 2. 修改配置文件:/etc/salt/master interface: 0.0.0.0 # 表示Master的IP 3. 啓動 service salt-master start """ slave端: """ 1. 安裝salt-minion yum install salt-minion 2. 修改配置文件 /etc/salt/minion master: 10.211.55.4 # master的地址 或 master: - 10.211.55.4 - 10.211.55.5 random_master: True id: c2.salt.com # 客戶端在salt-master中顯示的惟一ID 3. 啓動 service salt-minion start """
2:受權
""" salt-key -L # 查看已受權和未受權的slave salt-key -a salve_id # 接受指定id的salve salt-key -r salve_id # 拒絕指定id的salve salt-key -d salve_id # 刪除指定id的salve """
3:執行命令
在master服務器上對salve進行遠程操做
salt 'c2.salt.com' cmd.run 'ifconfig'
基於API的方式
import salt.client local = salt.client.LocalClient() result = local.cmd('c2.salt.com', 'cmd.run', ['ifconfig'])
參考安裝:
http://www.cnblogs.com/tim1blog/p/9987313.html
https://www.jianshu.com/p/84de3e012753
每隔30分鐘,經過RPC消息隊列將執行的結果返回給用戶
AES介紹
from Crypto.Cipher import AES def encrypt(message): key = b'dfdsdfsasdfdsdfs' cipher = AES.new(key, AES.MODE_CBC, key) ba_data = bytearray(message,encoding='utf-8') v1 = len(ba_data) v2 = v1 % 16 if v2 == 0: v3 = 16 else: v3 = 16 - v2 for i in range(v3): ba_data.append(v3) final_data = ba_data.decode('utf-8') msg = cipher.encrypt(final_data) # 要加密的字符串,必須是16個字節或16個字節的倍數 return msg # ############################## 解密 ############################## def decrypt(msg): from Crypto.Cipher import AES key = b'dfdsdfsasdfdsdfs' cipher = AES.new(key, AES.MODE_CBC, key) result = cipher.decrypt(msg) # result = b'\xe8\xa6\x81\xe5\x8a\xa0\xe5\xaf\x86\xe5\x8a\xa0\xe5\xaf\x86\xe5\x8a\xa0sdfsd\t\t\t\t\t\t\t\t\t' data = result[0:-result[-1]] return str(data,encoding='utf-8') msg = encrypt('你好好愛好愛好sss') res = decrypt(msg) print(res)
字符串格式化字符
String.prototype.format = function(args){ return this.replace(/\{(\w+)\}/g, function(s, i){ return args[i]; }); };
from django.db import models class UserProfile(models.Model): """ 用戶信息 """ name = models.CharField(u'姓名', max_length=32) email = models.EmailField(u'郵箱') phone = models.CharField(u'座機', max_length=32) mobile = models.CharField(u'手機', max_length=32) password = models.CharField(u'密碼', max_length=64) class Meta: verbose_name_plural = "用戶表" def __str__(self): return self.name class UserGroup(models.Model): """ 用戶組 """ name = models.CharField(max_length=32, unique=True) users = models.ManyToManyField('UserProfile') class Meta: verbose_name_plural = "用戶組表" def __str__(self): return self.name class BusinessUnit(models.Model): """ 業務線 """ name = models.CharField('業務線', max_length=64, unique=True) contact = models.ForeignKey('UserGroup', verbose_name='業務聯繫人', related_name='c') manager = models.ForeignKey('UserGroup', verbose_name='系統管理員', related_name='m') class Meta: verbose_name_plural = "業務線表" def __str__(self): return self.name class IDC(models.Model): """ 機房信息 """ name = models.CharField('機房', max_length=32) floor = models.IntegerField('樓層', default=1) class Meta: verbose_name_plural = "機房表" def __str__(self): return self.name class Tag(models.Model): """ 資產標籤 """ name = models.CharField('標籤', max_length=32, unique=True) class Meta: verbose_name_plural = "標籤表" def __str__(self): return self.name class Asset(models.Model): """ 資產信息表,全部資產公共信息(交換機,服務器,防火牆等) """ device_type_choices = ( (1, '服務器'), (2, '交換機'), (3, '防火牆'), ) device_status_choices = ( (1, '上架'), (2, '在線'), (3, '離線'), (4, '下架'), ) device_type_id = models.IntegerField(choices=device_type_choices, default=1) device_status_id = models.IntegerField(choices=device_status_choices, default=1) cabinet_num = models.CharField('機櫃號', max_length=30, null=True, blank=True) cabinet_order = models.CharField('機櫃中序號', max_length=30, null=True, blank=True) idc = models.ForeignKey('IDC', verbose_name='IDC機房', null=True, blank=True) business_unit = models.ForeignKey('BusinessUnit', verbose_name='屬於的業務線', null=True, blank=True) tag = models.ManyToManyField('Tag') latest_date = models.DateField(null=True) create_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name_plural = "資產表" def __str__(self): return "%s-%s-%s" % (self.idc.name, self.cabinet_num, self.cabinet_order) class NetworkDevice(models.Model): asset = models.OneToOneField('Asset') management_ip = models.CharField('管理IP', max_length=64, blank=True, null=True) vlan_ip = models.CharField('VlanIP', max_length=64, blank=True, null=True) intranet_ip = models.CharField('內網IP', max_length=128, blank=True, null=True) sn = models.CharField('SN號', max_length=64, unique=True) manufacture = models.CharField(verbose_name=u'製造商', max_length=128, null=True, blank=True) model = models.CharField('型號', max_length=128, null=True, blank=True) port_num = models.SmallIntegerField('端口個數', null=True, blank=True) device_detail = models.CharField('設置詳細配置', max_length=255, null=True, blank=True) class Meta: verbose_name_plural = "網絡設備" class Server(models.Model): """ 服務器信息 """ asset = models.OneToOneField('Asset') hostname = models.CharField(max_length=128, unique=True) sn = models.CharField('SN號', max_length=64, db_index=True) manufacturer = models.CharField(verbose_name='製造商', max_length=64, null=True, blank=True) model = models.CharField('型號', max_length=64, null=True, blank=True) manage_ip = models.GenericIPAddressField('管理IP', null=True, blank=True) os_platform = models.CharField('系統', max_length=16, null=True, blank=True) os_version = models.CharField('系統版本', max_length=16, null=True, blank=True) cpu_count = models.IntegerField('CPU個數', null=True, blank=True) cpu_physical_count = models.IntegerField('CPU物理個數', null=True, blank=True) cpu_model = models.CharField('CPU型號', max_length=128, null=True, blank=True) create_at = models.DateTimeField(auto_now_add=True, blank=True) class Meta: verbose_name_plural = "服務器表" def __str__(self): return self.hostname class Disk(models.Model): """ 硬盤信息 """ slot = models.CharField('插槽位', max_length=8) model = models.CharField('磁盤型號', max_length=32) capacity = models.FloatField('磁盤容量GB') pd_type = models.CharField('磁盤類型', max_length=32) server_obj = models.ForeignKey('Server',related_name='disk') class Meta: verbose_name_plural = "硬盤表" def __str__(self): return self.slot class NIC(models.Model): """ 網卡信息 """ name = models.CharField('網卡名稱', max_length=128) hwaddr = models.CharField('網卡mac地址', max_length=64) netmask = models.CharField(max_length=64) ipaddrs = models.CharField('ip地址', max_length=256) up = models.BooleanField(default=False) server_obj = models.ForeignKey('Server',related_name='nic') class Meta: verbose_name_plural = "網卡表" def __str__(self): return self.name class Memory(models.Model): """ 內存信息 """ slot = models.CharField('插槽位', max_length=32) manufacturer = models.CharField('製造商', max_length=32, null=True, blank=True) model = models.CharField('型號', max_length=64) capacity = models.FloatField('容量', null=True, blank=True) sn = models.CharField('內存SN號', max_length=64, null=True, blank=True) speed = models.CharField('速度', max_length=16, null=True, blank=True) server_obj = models.ForeignKey('Server',related_name='memory') class Meta: verbose_name_plural = "內存表" def __str__(self): return self.slot class AssetRecord(models.Model): """ 資產變動記錄,creator爲空時,表示是資產彙報的數據。 """ asset_obj = models.ForeignKey('Asset', related_name='ar') content = models.TextField(null=True)# 新增硬盤 creator = models.ForeignKey('UserProfile', null=True, blank=True) # create_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name_plural = "資產記錄表" def __str__(self): return "%s-%s-%s" % (self.asset_obj.idc.name, self.asset_obj.cabinet_num, self.asset_obj.cabinet_order) class ErrorLog(models.Model): """ 錯誤日誌,如:agent採集數據錯誤 或 運行錯誤 """ asset_obj = models.ForeignKey('Asset', null=True, blank=True) title = models.CharField(max_length=16) content = models.TextField() create_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name_plural = "錯誤日誌表" def __str__(self): return self.title