CMDB

一:IT運維的分類

  IT運維,指的是對已經搭建好的網絡、軟件、硬件進行維護。運維領域也是細分的,有硬件運維和軟件運維。html

  硬件運維主要包括對基礎設施的運維,例如機房的設備,主機的鍵盤,內存等物理設備的維護。web

  軟件運維主要包括系統運維和應用運維,系統運維主要包括對OS,數據庫,中間件的監控和維護,這些系統介於設備和應用之間,應用運維主要是對線上業務系統的運維。shell

  這裏主要討論的是軟件運維的自動化,包括系統運維和應用運維的自動化。數據庫

二:傳統運維的缺點

  1:平常工做繁瑣

  平常運維工做繁瑣,研發會常常須要到服務器上查看日誌,重啓應用,或者是上線某個產品須要部署環境等,都是運維的平常。django

  2:應用運行環境不統一

  在部署某個應用後,應用不能訪問,在開發環境運行的好,可是在測試環境後就不能繼續用了,由於各種環境的類庫不統一。還有一種狀況是,因爲運維人員的習慣不一樣,按照本身的習慣來安裝部署環境,每種服務器上運行的軟件目錄不統一。服務器

  3:運維及部署效率低下

  運維人員須要登陸到服務器上執行命令,部署程序,不只效率低,而且很是容易出現人爲錯誤,人爲出錯以後也不容易找到問題所在。網絡

  4:無用報警信息過多

  運維人員常常會收到不少的無用報警信息,經常會選擇屏蔽這些報警信息,而且一旦應用的訪問速度出了問題,就須要從系統、網絡、應用、數據庫等一步步查找信息。app

  5:資產管理和應用系統混亂

  資產管理,服務管理常常記錄在Excel或者文本里面,不便於管理。老員工因爲熟悉不注重文檔的維護,新員工入職時,資產才能更正一次。運維

三:爲何須要自動化運維?

  1:項目上線

  流程:產品經理調研(畫出原型圖)-->定需求-->三方會談(研發,產品經理,老大們)-->定日期-->測試項目-->最終上線-->應用運維dom

  目前:將代碼打包給運維,運維解壓上線

  問題:隨着機器數量的線性增長,運維的工做量也是線性增長,重複並且是毫無心義的勞動

  解決:

    1:寫一個shell腳本,進行部署

    2:搞一個自動化代碼上線系統

      必要條件:服務器的各類信息(主機名,CPU,硬盤大小等)

  2:監控系統

  監測服務器的各類信息(硬盤是否滿,CPU的使用率,內存使用率,網站服務運行是否正常)

  問題:以前簡單的腳本,監測服務器的信息,比較麻煩

  解決:想將服務器的各類信息,以圖表的形式展現在web界面上(可視化)

  必要條件:服務器的各類信息(主機名,CPU,硬盤大小等)

  3:自動裝機系統

  問題:人工裝機須要一臺一臺去裝

  解決:搞一個裝機系統,cobbler軟件

  必要條件:服務器的各類信息(主機名,CPU等)

  4:Excel表格審計管理資產

四:資產管理系統(CMDB)

CMDB是全部運維工具的數據基礎,CMDB全稱Configuration Management Database

1,CMDB包含的功能:

  1:用戶管理,記錄測試,開發,運維人員的用戶表

  2:業務線管理,須要記錄業務的詳情

  3:項目管理,指定此項目需屬於那條業務線,以及項目詳情

  4:應用管理,指定此應用的開發人員,屬於哪一個項目,和代碼地址,部署目錄,部署集羣,依賴的應用,軟件等信息。

  5:主機管理,包括雲主機,物理機,主機屬於哪一個集羣,運行着哪些軟件,主機管理員,鏈接着哪些網絡設備,雲主機的資源地,存儲等相關信息。

  6:主機變動管理,主機的一些信息變動,例如管理員,所屬集羣等信息更改,鏈接的網絡變動等。

  7:網絡設備管理,主要記錄網絡設備的詳細信息,及網絡設備鏈接的上級設備

  8:IP管理,IP屬於哪一個主機,哪一個網段,是否被佔用等

2,CMDB實現的四種方式:

  方式一:Agent方式

  能夠將服務器上面的Agent程序做定時任務,定時將資產信息提交到指定API錄入數據庫

本質就是在各個服務器上執行subprocess.getoutput("命令"),而後將每臺機器上執行的結果返回給主句API,而後主機API收到這些數據以後,放到數據庫中,最終經過web界面展示給用戶。

優勢:速度快
缺點:須要爲每臺服務器部署有關Agent程序
使用場景:服務器比較多的時候

  方式二:ssh類實現方式(基於paramiko模塊)

  中控機經過Paramiko(py模塊)登陸到各個服務器上,而後執行命令的方式去獲取各個服務器上的信息。

優勢:沒有Agent
缺點:有一箇中控機,速度慢
使用場景:服務器比較少的時候

  方式三:salt-stack方式

此方案本質上和第二種方案是差很少的流程,中控機發送命令給服務器執行。服務器將結果放入另外一個隊列中,中控機獲取將服務信息發送到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
"""
View Code

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
"""
View Code

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

  方式四:puppet方式(Ruby寫的,瞭解)

  每隔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)
View Code

字符串格式化字符

String.prototype.format = function(args){
        return this.replace(/\{(\w+)\}/g, function(s, i){
            return args[i];
        });
    };
View Code

 CMDB表結構

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
models
相關文章
相關標籤/搜索