森 宝松 SIer Tech Blog

【「動作保証はどこまで?」SIerのためのシステム保守の基本】

森 宝松
SIer Tech Blog
2025年3月25日

【「動作保証はどこまで?」SIerのためのシステム保守の基本】

業務システムの保守は、SIerにとって重要な責務の一つです。本記事では、システム保守の範囲定義から具体的な保守活動まで、実践的なアプローチを解説します。

1. システム保守の基本概念

1.1 保守の種類と範囲

システム保守は以下の4つの種類に分類されます:

  1. 是正保守:バグ修正や障害対応
  2. 予防保守:将来的な問題の予防
  3. 適応保守:環境変化への対応
  4. 完全化保守:機能改善や拡張

1.2 保守範囲の定義

// 保守範囲を定義するクラスの例
@Data
@Builder
public class MaintenanceScope {
    // 保守対象システム
    private List<SystemComponent> targetSystems;
    
    // 保守レベル
    private MaintenanceLevel level;
    
    // サービス時間
    private ServiceHours serviceHours;
    
    // 応答時間
    private ResponseTime responseTime;
    
    // 除外事項
    private List<ExclusionItem> exclusions;
}

// 保守レベルの定義
public enum MaintenanceLevel {
    BASIC(Arrays.asList(
        MaintenanceType.CORRECTIVE,
        MaintenanceType.PREVENTIVE
    )),
    
    STANDARD(Arrays.asList(
        MaintenanceType.CORRECTIVE,
        MaintenanceType.PREVENTIVE,
        MaintenanceType.ADAPTIVE
    )),
    
    PREMIUM(Arrays.asList(
        MaintenanceType.CORRECTIVE,
        MaintenanceType.PREVENTIVE,
        MaintenanceType.ADAPTIVE,
        MaintenanceType.PERFECTIVE
    ));
    
    private final List<MaintenanceType> includedTypes;
    
    MaintenanceLevel(List<MaintenanceType> types) {
        this.includedTypes = types;
    }
}

// サービス時間の定義
@Data
public class ServiceHours {
    private DayOfWeek[] workingDays;
    private LocalTime startTime;
    private LocalTime endTime;
    private boolean includesHolidays;
    
    public boolean isWithinServiceHours(LocalDateTime dateTime) {
        // 営業時間内かどうかの判定ロジック
        if (!Arrays.asList(workingDays).contains(dateTime.getDayOfWeek())) {
            return false;
        }
        
        LocalTime time = dateTime.toLocalTime();
        return !time.isBefore(startTime) && !time.isAfter(endTime);
    }
}

2. SLAの設計と管理

2.1 SLA項目の定義

// SLA定義の例
@Data
@Builder
public class ServiceLevelAgreement {
    // 可用性要件
    private Availability availability;
    
    // 性能要件
    private Performance performance;
    
    // 信頼性要件
    private Reliability reliability;
    
    // サポート要件
    private Support support;
}

// 可用性の定義
@Data
public class Availability {
    // 稼働率目標
    private BigDecimal targetUptime;
    
    // 計画停止の上限
    private Duration maxPlannedDowntime;
    
    // 計画外停止の上限
    private Duration maxUnplannedDowntime;
    
    public boolean isWithinSLA(SystemMetrics metrics) {
        BigDecimal actualUptime = calculateActualUptime(metrics);
        return actualUptime.compareTo(targetUptime) >= 0;
    }
}

// 性能要件の定義
@Data
public class Performance {
    // レスポンスタイムの目標
    private Duration targetResponseTime;
    
    // スループットの目標
    private int targetThroughput;
    
    // 同時接続数の上限
    private int maxConcurrentUsers;
    
    public boolean isWithinSLA(SystemMetrics metrics) {
        return metrics.getAverageResponseTime().compareTo(targetResponseTime) <= 0 &&
               metrics.getThroughput() >= targetThroughput;
    }
}

2.2 SLA監視の実装

// SLA監視サービスの実装例
@Service
public class SLAMonitoringService {
    private final MetricsCollector metricsCollector;
    private final AlertService alertService;
    private final SLAReportGenerator reportGenerator;
    
    @Scheduled(fixedRate = 300000) // 5分ごとに実行
    public void monitorSLA() {
        // メトリクスの収集
        SystemMetrics metrics = metricsCollector.collectMetrics();
        
        // SLAの評価
        evaluateSLA(metrics);
        
        // レポートの生成
        generateSLAReport(metrics);
    }
    
    private void evaluateSLA(SystemMetrics metrics) {
        // 可用性の評価
        if (!sla.getAvailability().isWithinSLA(metrics)) {
            alertService.sendAlert(
                AlertLevel.HIGH,
                "Availability SLA violation detected",
                createAlertDetails(metrics)
            );
        }
        
        // 性能の評価
        if (!sla.getPerformance().isWithinSLA(metrics)) {
            alertService.sendAlert(
                AlertLevel.WARNING,
                "Performance SLA violation detected",
                createAlertDetails(metrics)
            );
        }
    }
    
    private void generateSLAReport(SystemMetrics metrics) {
        SLAReport report = reportGenerator.generateReport(metrics);
        
        // レポートの保存と配布
        reportRepository.save(report);
        notificationService.distributeReport(report);
    }
}

// メトリクス収集の実装
@Service
public class MetricsCollector {
    private final MeterRegistry registry;
    
    public SystemMetrics collectMetrics() {
        return SystemMetrics.builder()
            .availability(calculateAvailability())
            .responseTime(calculateResponseTime())
            .throughput(calculateThroughput())
            .errorRate(calculateErrorRate())
            .build();
    }
    
    private BigDecimal calculateAvailability() {
        Timer uptime = registry.timer("system.uptime");
        Timer downtime = registry.timer("system.downtime");
        
        return BigDecimal.valueOf(uptime.totalTime(TimeUnit.SECONDS))
            .divide(BigDecimal.valueOf(
                uptime.totalTime(TimeUnit.SECONDS) +
                downtime.totalTime(TimeUnit.SECONDS)
            ), 4, RoundingMode.HALF_UP);
    }
}

3. 保守作業の実践

3.1 定期保守の実装

// 定期保守タスクの実装例
@Service
public class RegularMaintenanceService {
    private final SystemHealthChecker healthChecker;
    private final DatabaseOptimizer dbOptimizer;
    private final LogManager logManager;
    
    @Scheduled(cron = "0 0 1 * * SUN") // 毎週日曜日の午前1時に実行
    public void performWeeklyMaintenance() {
        try {
            // システム状態チェック
            healthChecker.checkSystemHealth();
            
            // データベース最適化
            dbOptimizer.optimize();
            
            // ログファイルの整理
            logManager.cleanup();
            
            // メンテナンス結果の記録
            recordMaintenanceResult();
            
        } catch (Exception e) {
            handleMaintenanceError(e);
        }
    }
    
    // データベース最適化の実装
    @Service
    public class DatabaseOptimizer {
        public void optimize() {
            // テーブル統計情報の更新
            updateTableStatistics();
            
            // インデックスの再構築
            rebuildIndexes();
            
            // 不要データの削除
            cleanupOldData();
        }
        
        private void updateTableStatistics() {
            jdbcTemplate.execute("ANALYZE VERBOSE");
        }
        
        private void rebuildIndexes() {
            List<String> tables = getTargetTables();
            for (String table : tables) {
                jdbcTemplate.execute("REINDEX TABLE " + table);
            }
        }
    }
}

3.2 障害対応の実装

// 障害対応サービスの実装例
@Service
public class IncidentManagementService {
    private final IncidentRepository repository;
    private final NotificationService notificationService;
    private final RecoveryService recoveryService;
    
    public Incident handleIncident(IncidentReport report) {
        // インシデントの登録
        Incident incident = createIncident(report);
        
        // 影響度の評価
        assessImpact(incident);
        
        // 対応チームへの通知
        notifyTeam(incident);
        
        // 復旧作業の開始
        startRecovery(incident);
        
        return incident;
    }
    
    private void assessImpact(Incident incident) {
        ImpactAssessment assessment = ImpactAssessment.builder()
            .affectedUsers(calculateAffectedUsers(incident))
            .businessImpact(evaluateBusinessImpact(incident))
            .systemImpact(evaluateSystemImpact(incident))
            .build();
        
        incident.setImpactAssessment(assessment);
        incident.setPriority(determinePriority(assessment));
    }
    
    private void startRecovery(Incident incident) {
        RecoveryPlan plan = recoveryService.createRecoveryPlan(incident);
        
        // 復旧作業の実行
        recoveryService.executeRecoveryPlan(plan);
        
        // 進捗の監視
        monitorRecoveryProgress(plan);
    }
}

// 復旧サービスの実装
@Service
public class RecoveryService {
    public RecoveryPlan createRecoveryPlan(Incident incident) {
        return RecoveryPlan.builder()
            .steps(determineRecoverySteps(incident))
            .estimatedTime(calculateEstimatedTime(incident))
            .requiredResources(identifyRequiredResources(incident))
            .build();
    }
    
    public void executeRecoveryPlan(RecoveryPlan plan) {
        for (RecoveryStep step : plan.getSteps()) {
            try {
                executeStep(step);
                verifyStepCompletion(step);
                
            } catch (Exception e) {
                handleStepFailure(step, e);
                
                if (isStepCritical(step)) {
                    throw new RecoveryFailedException(
                        "Critical step failed: " + step.getName(),
                        e
                    );
                }
            }
        }
    }
}

4. 予防保守の実践

4.1 システム監視の実装

// システム監視サービスの実装例
@Service
public class SystemMonitoringService {
    private final MetricsCollector metricsCollector;
    private final AlertService alertService;
    private final PredictiveAnalyzer predictiveAnalyzer;
    
    @Scheduled(fixedRate = 60000) // 1分ごとに実行
    public void monitorSystem() {
        // システムメトリクスの収集
        SystemMetrics metrics = metricsCollector.collectMetrics();
        
        // 現在の状態の評価
        evaluateCurrentState(metrics);
        
        // 将来の問題の予測
        predictFutureIssues(metrics);
    }
    
    private void evaluateCurrentState(SystemMetrics metrics) {
        // リソース使用率の確認
        checkResourceUtilization(metrics);
        
        // パフォーマンスの確認
        checkPerformance(metrics);
        
        // エラー率の確認
        checkErrorRate(metrics);
    }
    
    private void predictFutureIssues(SystemMetrics metrics) {
        // トレンド分析
        List<Trend> trends = predictiveAnalyzer.analyzeTrends(metrics);
        
        // 問題の予測
        List<PredictedIssue> predictedIssues = 
            predictiveAnalyzer.predictIssues(trends);
        
        // 予防的アラートの送信
        for (PredictedIssue issue : predictedIssues) {
            alertService.sendPreventiveAlert(issue);
        }
    }
}

// 予測分析の実装
@Service
public class PredictiveAnalyzer {
    public List<Trend> analyzeTrends(SystemMetrics metrics) {
        List<Trend> trends = new ArrayList<>();
        
        // CPU使用率のトレンド
        trends.add(analyzeCpuTrend(metrics));
        
        // メモリ使用率のトレンド
        trends.add(analyzeMemoryTrend(metrics));
        
        // ディスク使用率のトレンド
        trends.add(analyzeDiskTrend(metrics));
        
        // レスポンスタイムのトレンド
        trends.add(analyzeResponseTimeTrend(metrics));
        
        return trends;
    }
    
    public List<PredictedIssue> predictIssues(List<Trend> trends) {
        List<PredictedIssue> issues = new ArrayList<>();
        
        for (Trend trend : trends) {
            if (trend.indicatesPotentialIssue()) {
                issues.add(createPredictedIssue(trend));
            }
        }
        
        return issues;
    }
}

4.2 性能チューニング

// 性能チューニングサービスの実装例
@Service
public class PerformanceOptimizationService {
    private final DatabaseOptimizer dbOptimizer;
    private final CacheOptimizer cacheOptimizer;
    private final QueryOptimizer queryOptimizer;
    
    public OptimizationResult optimizePerformance() {
        OptimizationResult result = new OptimizationResult();
        
        // データベースの最適化
        result.addDatabaseOptimizations(
            dbOptimizer.optimize()
        );
        
        // キャッシュの最適化
        result.addCacheOptimizations(
            cacheOptimizer.optimize()
        );
        
        // クエリの最適化
        result.addQueryOptimizations(
            queryOptimizer.optimize()
        );
        
        return result;
    }
}

// データベース最適化の実装
@Service
public class DatabaseOptimizer {
    public List<OptimizationAction> optimize() {
        List<OptimizationAction> actions = new ArrayList<>();
        
        // インデックスの分析と最適化
        actions.addAll(optimizeIndexes());
        
        // テーブル統計情報の更新
        actions.addAll(updateStatistics());
        
        // パーティションの最適化
        actions.addAll(optimizePartitions());
        
        return actions;
    }
    
    private List<OptimizationAction> optimizeIndexes() {
        List<OptimizationAction> actions = new ArrayList<>();
        
        // 未使用インデックスの特定
        List<String> unusedIndexes = findUnusedIndexes();
        for (String index : unusedIndexes) {
            actions.add(new DropIndexAction(index));
        }
        
        // 断片化したインデックスの再構築
        List<String> fragmentedIndexes = findFragmentedIndexes();
        for (String index : fragmentedIndexes) {
            actions.add(new RebuildIndexAction(index));
        }
        
        return actions;
    }
}

5. 保守ドキュメントの管理

5.1 ドキュメント体系の整備

// ドキュメント管理システムの実装例
@Service
public class DocumentationManager {
    private final DocumentRepository repository;
    private final VersionControl versionControl;
    private final DocumentValidator validator;
    
    public Document createDocument(DocumentType type, String content) {
        // ドキュメントの作成
        Document document = new Document();
        document.setType(type);
        document.setContent(content);
        
        // バリデーション
        validator.validate(document);
        
        // バージョン管理
        versionControl.createVersion(document);
        
        // 保存
        return repository.save(document);
    }
    
    public void updateDocument(Document document) {
        // 変更の検証
        validator.validateUpdate(document);
        
        // 新しいバージョンの作成
        versionControl.createVersion(document);
        
        // 更新の保存
        repository.save(document);
    }
}

// ドキュメントの種類
public enum DocumentType {
    SYSTEM_OVERVIEW(Arrays.asList(
        DocumentSection.SYSTEM_ARCHITECTURE,
        DocumentSection.COMPONENT_DIAGRAM,
        DocumentSection.TECHNOLOGY_STACK
    )),
    
    OPERATION_MANUAL(Arrays.asList(
        DocumentSection.STARTUP_PROCEDURE,
        DocumentSection.SHUTDOWN_PROCEDURE,
        DocumentSection.BACKUP_PROCEDURE
    )),
    
    MAINTENANCE_GUIDE(Arrays.asList(
        DocumentSection.REGULAR_MAINTENANCE,
        DocumentSection.TROUBLESHOOTING,
        DocumentSection.RECOVERY_PROCEDURE
    ));
    
    private final List<DocumentSection> requiredSections;
    
    DocumentType(List<DocumentSection> sections) {
        this.requiredSections = sections;
    }
}

5.2 変更管理の実装

// 変更管理システムの実装例
@Service
public class ChangeManagementService {
    private final ChangeRepository repository;
    private final ApprovalService approvalService;
    private final ImpactAnalyzer impactAnalyzer;
    
    public Change requestChange(ChangeRequest request) {
        // 変更の登録
        Change change = createChange(request);
        
        // 影響分析
        analyzeImpact(change);
        
        // 承認フローの開始
        startApprovalFlow(change);
        
        return change;
    }
    
    private void analyzeImpact(Change change) {
        ImpactAnalysis analysis = impactAnalyzer.analyze(change);
        
        // リスクレベルの判定
        RiskLevel riskLevel = determineRiskLevel(analysis);
        change.setRiskLevel(riskLevel);
        
        // 必要な承認レベルの設定
        ApprovalLevel requiredApproval = determineRequiredApproval(riskLevel);
        change.setRequiredApprovalLevel(requiredApproval);
    }
    
    private void startApprovalFlow(Change change) {
        ApprovalFlow flow = approvalService.createFlow(
            change.getRequiredApprovalLevel()
        );
        
        // 承認者への通知
        notifyApprovers(flow.getApprovers());
        
        // 承認状況の監視開始
        monitorApprovalStatus(change, flow);
    }
}

6. まとめ

システム保守は、以下の点に注意を払いながら計画的に実施することが重要です:

  1. 保守範囲の明確化

    • 保守対象の明確な定義
    • SLAの適切な設定
    • 除外事項の明確化
  2. 予防的アプローチ

    • 定期的な監視と分析
    • 予防的なメンテナンス
    • 性能の最適化
  3. 効果的な運用管理

    • 変更管理の徹底
    • ドキュメントの整備
    • チーム間の連携

参考文献

  1. 「実践システム保守」- 技術評論社
  2. 「ITサービスマネジメント」- 日経BP
  3. 「システム運用の基本」- 翔泳社
  4. 「SLA設計の実践」- インプレス

システム保守は、システムの安定運用と継続的な改善を支える重要な活動です。本記事で紹介したアプローチを参考に、効果的な保守体制を構築してください。

関連記事

2025/3/24

【SIerが知るべきログ設計のベストプラクティス】

SIerエンジニアのためのログ設計ガイド。業務システムにおける効果的なログ設計から運用管理まで、実践的なベストプラクティスを解説します。

2025/3/23

【長年運用されている業務システムの"負債"とどう向き合うか?】

SIerエンジニアのための技術的負債管理ガイド。長年運用されてきた業務システムの負債を理解し、効果的に管理・改善していくための実践的なアプローチを解説します。

2025/3/22

【SIerのための「障害対応力」向上マニュアル】

SIerエンジニアのための実践的な障害対応ガイド。初動対応から原因分析、再発防止まで、現場で必要な知識とスキルを解説します。