CMDB


一:IT運維的分類

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

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

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

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

二:傳統運維的缺點

  1:日常工作繁瑣

  日常運維工作繁瑣,研發會經常需要到服務器上查看日志,重啟應用,或者是上線某個產品需要部署環境等,都是運維的日常。

  2:應用運行環境不統一

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

  3:運維及部署效率低下

  運維人員需要登錄到服務器上執行命令,部署程序,不僅效率低,並且非常容易出現人為錯誤,人為出錯之后也不容易找到問題所在。

  4:無用報警信息過多

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

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

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

三:為什么需要自動化運維?

  1:項目上線

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

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

  問題:隨着機器數量的線性增加,運維的工作量也是線性增加,重復而且是毫無意義的勞動

  解決:

    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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM