sync
This commit is contained in:
209
.kiro/specs/applescript-calendar-sync/design.md
Normal file
209
.kiro/specs/applescript-calendar-sync/design.md
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
# Design Document
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The AppleScript Calendar Sync system is designed as a standalone AppleScript application that synchronizes calendar events between two calendar accounts for the current day only. The system uses macOS Calendar app's AppleScript interface to read events from a source calendar and mirror them to a destination calendar, including removal of events that no longer exist in the source.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
The system follows a simple pipeline architecture:
|
||||||
|
|
||||||
|
```
|
||||||
|
[Source Calendar] → [Event Reader] → [Event Processor] → [Destination Calendar]
|
||||||
|
↓
|
||||||
|
[Duplicate Detector]
|
||||||
|
↓
|
||||||
|
[Cleanup Manager]
|
||||||
|
```
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
|
||||||
|
1. **Calendar Manager**: Handles calendar account and calendar selection/validation
|
||||||
|
2. **Event Reader**: Retrieves events from source calendar for current day
|
||||||
|
3. **Event Processor**: Processes and transforms events for destination calendar
|
||||||
|
4. **Sync Engine**: Coordinates the synchronization process including cleanup
|
||||||
|
5. **Logger**: Provides user feedback and error reporting
|
||||||
|
|
||||||
|
## Components and Interfaces
|
||||||
|
|
||||||
|
### Calendar Manager
|
||||||
|
```applescript
|
||||||
|
-- Validates and retrieves calendar references
|
||||||
|
on getCalendar(accountName, calendarName)
|
||||||
|
on validateCalendarAccess(calendar)
|
||||||
|
on listAvailableCalendars()
|
||||||
|
```
|
||||||
|
|
||||||
|
**Responsibilities:**
|
||||||
|
- Validate calendar account and calendar names exist
|
||||||
|
- Return calendar object references for AppleScript operations
|
||||||
|
- Handle calendar access permissions and errors
|
||||||
|
|
||||||
|
### Event Reader
|
||||||
|
```applescript
|
||||||
|
-- Reads events from source calendar for current day
|
||||||
|
on getEventsForToday(sourceCalendar)
|
||||||
|
on parseEventProperties(event)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Responsibilities:**
|
||||||
|
- Query source calendar for events occurring on current date
|
||||||
|
- Extract event properties (title, start time, end time, description, etc.)
|
||||||
|
- Handle different event types (all-day, timed, recurring)
|
||||||
|
|
||||||
|
### Event Processor
|
||||||
|
```applescript
|
||||||
|
-- Processes events for destination calendar
|
||||||
|
on createEventInDestination(eventData, destinationCalendar)
|
||||||
|
on updateExistingEvent(existingEvent, newEventData)
|
||||||
|
on compareEvents(event1, event2)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Responsibilities:**
|
||||||
|
- Create new events in destination calendar
|
||||||
|
- Update modified events
|
||||||
|
- Compare events for duplicate detection
|
||||||
|
|
||||||
|
### Sync Engine
|
||||||
|
```applescript
|
||||||
|
-- Main synchronization coordinator
|
||||||
|
on performSync(sourceCalendar, destinationCalendar)
|
||||||
|
on cleanupRemovedEvents(sourceEvents, destinationEvents, destinationCalendar)
|
||||||
|
on generateSyncReport(results)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Responsibilities:**
|
||||||
|
- Coordinate the entire sync process
|
||||||
|
- Manage event cleanup (removal of events not in source)
|
||||||
|
- Generate sync reports and statistics
|
||||||
|
|
||||||
|
### Logger
|
||||||
|
```applescript
|
||||||
|
-- Logging and user feedback
|
||||||
|
on logMessage(message, level)
|
||||||
|
on displayProgress(current, total)
|
||||||
|
on showSyncSummary(summary)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Responsibilities:**
|
||||||
|
- Display progress information to user
|
||||||
|
- Log errors and warnings
|
||||||
|
- Show final sync summary
|
||||||
|
|
||||||
|
## Data Models
|
||||||
|
|
||||||
|
### Event Data Structure
|
||||||
|
```applescript
|
||||||
|
record EventData
|
||||||
|
title: string
|
||||||
|
startDate: date
|
||||||
|
endDate: date
|
||||||
|
isAllDay: boolean
|
||||||
|
description: string
|
||||||
|
location: string
|
||||||
|
uid: string (for duplicate detection)
|
||||||
|
end record
|
||||||
|
```
|
||||||
|
|
||||||
|
### Sync Result Structure
|
||||||
|
```applescript
|
||||||
|
record SyncResult
|
||||||
|
eventsCreated: integer
|
||||||
|
eventsUpdated: integer
|
||||||
|
eventsRemoved: integer
|
||||||
|
eventsSkipped: integer
|
||||||
|
errors: list of strings
|
||||||
|
end record
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Error Categories
|
||||||
|
1. **Calendar Access Errors**: Invalid calendar names, permission issues
|
||||||
|
2. **Event Processing Errors**: Malformed events, property access failures
|
||||||
|
3. **Sync Operation Errors**: Network issues, calendar service unavailable
|
||||||
|
|
||||||
|
### Error Handling Strategy
|
||||||
|
- Graceful degradation: Continue processing other events when individual events fail
|
||||||
|
- Detailed error logging with specific error messages
|
||||||
|
- User-friendly error reporting with suggested solutions
|
||||||
|
- Rollback capability for critical failures
|
||||||
|
|
||||||
|
### Error Recovery
|
||||||
|
```applescript
|
||||||
|
on handleCalendarError(errorMessage)
|
||||||
|
-- Log error details
|
||||||
|
-- Provide user-friendly error message
|
||||||
|
-- Suggest corrective actions
|
||||||
|
end handleCalendarError
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Strategy
|
||||||
|
|
||||||
|
### Unit Testing Approach
|
||||||
|
Since AppleScript has limited testing frameworks, testing will focus on:
|
||||||
|
|
||||||
|
1. **Manual Testing Scenarios**:
|
||||||
|
- Test with empty source calendar
|
||||||
|
- Test with events spanning multiple days
|
||||||
|
- Test with all-day events
|
||||||
|
- Test with recurring events
|
||||||
|
- Test calendar access errors
|
||||||
|
|
||||||
|
2. **Integration Testing**:
|
||||||
|
- Test full sync workflow with real calendar data
|
||||||
|
- Test cleanup functionality (event removal)
|
||||||
|
- Test duplicate detection accuracy
|
||||||
|
- Test error handling with invalid inputs
|
||||||
|
|
||||||
|
3. **Edge Case Testing**:
|
||||||
|
- Very long event titles and descriptions
|
||||||
|
- Events with special characters
|
||||||
|
- Overlapping events
|
||||||
|
- Events created/modified during sync
|
||||||
|
|
||||||
|
### Test Data Requirements
|
||||||
|
- Test calendars with known event sets
|
||||||
|
- Events with various properties (all-day, timed, recurring)
|
||||||
|
- Events with special characters and long descriptions
|
||||||
|
- Calendar accounts with different permission levels
|
||||||
|
|
||||||
|
## Implementation Considerations
|
||||||
|
|
||||||
|
### AppleScript Calendar Integration
|
||||||
|
- Use `Calendar` application's AppleScript dictionary
|
||||||
|
- Handle calendar app launch and focus management
|
||||||
|
- Manage calendar selection and event creation timing
|
||||||
|
|
||||||
|
### Performance Optimization
|
||||||
|
- Batch event operations where possible
|
||||||
|
- Minimize calendar app UI interactions
|
||||||
|
- Cache calendar references to avoid repeated lookups
|
||||||
|
|
||||||
|
### User Experience
|
||||||
|
- Provide clear progress indicators
|
||||||
|
- Show meaningful error messages
|
||||||
|
- Allow user to cancel long-running operations
|
||||||
|
- Display comprehensive sync results
|
||||||
|
|
||||||
|
### Security and Privacy
|
||||||
|
- Request calendar access permissions appropriately
|
||||||
|
- Handle sensitive calendar data securely
|
||||||
|
- Provide clear information about what data is accessed
|
||||||
|
|
||||||
|
## Configuration Management
|
||||||
|
|
||||||
|
### User Configuration
|
||||||
|
```applescript
|
||||||
|
-- Configuration properties
|
||||||
|
property sourceAccountName : "Work Account"
|
||||||
|
property sourceCalendarName : "Main Calendar"
|
||||||
|
property destinationAccountName : "Personal Account"
|
||||||
|
property destinationCalendarName : "Synced Events"
|
||||||
|
property enableLogging : true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Runtime Configuration
|
||||||
|
- Allow users to modify calendar names without editing script
|
||||||
|
- Provide configuration validation before sync starts
|
||||||
|
- Save user preferences for repeated use
|
||||||
73
.kiro/specs/applescript-calendar-sync/requirements.md
Normal file
73
.kiro/specs/applescript-calendar-sync/requirements.md
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# Requirements Document
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This feature enables automatic synchronization of calendar entries between two different calendar accounts using AppleScript. The system will copy events from a source calendar account to a destination calendar account, maintaining event details while avoiding duplicates and providing configurable sync options.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement 1
|
||||||
|
|
||||||
|
**User Story:** As a user with multiple calendar accounts, I want to sync events from one account to another, so that I can maintain consistent scheduling across different calendar systems.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the sync script is executed THEN the system SHALL read all events from the specified source calendar
|
||||||
|
2. WHEN events are found in the source calendar THEN the system SHALL copy them to the specified destination calendar
|
||||||
|
3. WHEN copying events THEN the system SHALL preserve event title, date, time, duration, and description
|
||||||
|
4. IF an event already exists in the destination calendar THEN the system SHALL skip creating a duplicate
|
||||||
|
|
||||||
|
### Requirement 2
|
||||||
|
|
||||||
|
**User Story:** As a user, I want to configure which calendars to sync between, so that I can control the data flow between my accounts.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN configuring the sync THEN the system SHALL allow selection of source calendar account and specific calendar
|
||||||
|
2. WHEN configuring the sync THEN the system SHALL allow selection of destination calendar account and specific calendar
|
||||||
|
3. WHEN invalid calendar names are provided THEN the system SHALL display an error message and exit gracefully
|
||||||
|
4. WHEN calendar accounts are not accessible THEN the system SHALL provide clear error messaging
|
||||||
|
|
||||||
|
### Requirement 3
|
||||||
|
|
||||||
|
**User Story:** As a user, I want the sync to focus on today's events only, so that I maintain current day synchronization without overwhelming the destination calendar.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the sync runs THEN the system SHALL only process events occurring on the current day
|
||||||
|
2. WHEN determining current day THEN the system SHALL use the local system date
|
||||||
|
3. WHEN events span multiple days THEN the system SHALL include events that start or occur on the current day
|
||||||
|
4. WHEN no events exist for the current day THEN the system SHALL complete successfully with appropriate messaging
|
||||||
|
|
||||||
|
### Requirement 4
|
||||||
|
|
||||||
|
**User Story:** As a user, I want the destination calendar to mirror the source calendar for the current day, so that removed events are also cleaned up automatically.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN checking for duplicates THEN the system SHALL compare event title, start date, and start time
|
||||||
|
2. WHEN a matching event is found in the destination THEN the system SHALL skip creating the duplicate
|
||||||
|
3. WHEN an event exists in the destination but not in the source for the current day THEN the system SHALL remove it from the destination
|
||||||
|
4. WHEN an event has been modified in the source THEN the system SHALL update the corresponding event in the destination
|
||||||
|
|
||||||
|
### Requirement 5
|
||||||
|
|
||||||
|
**User Story:** As a user, I want to see progress and results of the sync operation, so that I can verify the synchronization was successful.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the sync starts THEN the system SHALL display the source and destination calendar information
|
||||||
|
2. WHEN processing events THEN the system SHALL show progress indicators for each event processed
|
||||||
|
3. WHEN the sync completes THEN the system SHALL display a summary of events copied, skipped, and any errors
|
||||||
|
4. WHEN errors occur THEN the system SHALL log detailed error information for troubleshooting
|
||||||
|
|
||||||
|
### Requirement 6
|
||||||
|
|
||||||
|
**User Story:** As a user, I want the sync to handle different event types and properties, so that all my calendar data is accurately transferred.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN syncing events THEN the system SHALL handle all-day events correctly
|
||||||
|
2. WHEN syncing events THEN the system SHALL preserve recurring event patterns when possible
|
||||||
|
3. WHEN syncing events THEN the system SHALL handle events with attendees and meeting details
|
||||||
|
4. WHEN event properties cannot be transferred THEN the system SHALL log which properties were skipped
|
||||||
125
.kiro/specs/applescript-calendar-sync/tasks.md
Normal file
125
.kiro/specs/applescript-calendar-sync/tasks.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# Implementation Plan
|
||||||
|
|
||||||
|
- [x] 1. Set up project structure and configuration
|
||||||
|
- Create main AppleScript file with basic structure and configuration properties
|
||||||
|
- Define configuration properties for source and destination calendars
|
||||||
|
- Set up logging and error handling framework
|
||||||
|
- _Requirements: 2.1, 2.2, 5.1_
|
||||||
|
|
||||||
|
- [ ] 2. Implement Calendar Manager component
|
||||||
|
- [ ] 2.1 Create calendar validation and access functions
|
||||||
|
- Write functions to validate calendar account and calendar names exist
|
||||||
|
- Implement calendar object retrieval with error handling
|
||||||
|
- Create function to list available calendars for debugging
|
||||||
|
- _Requirements: 2.1, 2.2, 2.3, 2.4_
|
||||||
|
|
||||||
|
- [ ]* 2.2 Write unit tests for calendar access
|
||||||
|
- Create test scenarios for invalid calendar names
|
||||||
|
- Test calendar access permission handling
|
||||||
|
- _Requirements: 2.3, 2.4_
|
||||||
|
|
||||||
|
- [ ] 3. Implement Event Reader component
|
||||||
|
- [ ] 3.1 Create current day event retrieval function
|
||||||
|
- Write function to get today's date and create date range
|
||||||
|
- Implement event query for current day from source calendar
|
||||||
|
- Handle different event types (all-day, timed events)
|
||||||
|
- _Requirements: 1.1, 3.1, 3.2, 3.3_
|
||||||
|
|
||||||
|
- [ ] 3.2 Implement event property extraction
|
||||||
|
- Create function to extract event title, dates, description, location
|
||||||
|
- Handle event property access errors gracefully
|
||||||
|
- Parse recurring events for current day occurrences
|
||||||
|
- _Requirements: 1.3, 6.1, 6.2, 6.3_
|
||||||
|
|
||||||
|
- [ ]* 3.3 Write tests for event reading functionality
|
||||||
|
- Test event retrieval with various event types
|
||||||
|
- Test property extraction accuracy
|
||||||
|
- _Requirements: 1.1, 1.3_
|
||||||
|
|
||||||
|
- [ ] 4. Implement Event Processor component
|
||||||
|
- [ ] 4.1 Create event comparison and duplicate detection
|
||||||
|
- Write function to compare events by title, start date, and start time
|
||||||
|
- Implement duplicate detection logic for existing events
|
||||||
|
- Handle event matching edge cases
|
||||||
|
- _Requirements: 4.1, 4.2_
|
||||||
|
|
||||||
|
- [ ] 4.2 Implement event creation and update functions
|
||||||
|
- Create function to add new events to destination calendar
|
||||||
|
- Implement event update functionality for modified events
|
||||||
|
- Handle event creation errors and property limitations
|
||||||
|
- _Requirements: 1.2, 1.3, 4.4, 6.4_
|
||||||
|
|
||||||
|
- [ ]* 4.3 Write tests for event processing
|
||||||
|
- Test duplicate detection accuracy
|
||||||
|
- Test event creation with various properties
|
||||||
|
- _Requirements: 4.1, 4.2, 4.4_
|
||||||
|
|
||||||
|
- [ ] 5. Implement Sync Engine component
|
||||||
|
- [ ] 5.1 Create main synchronization workflow
|
||||||
|
- Implement the main sync function that coordinates all components
|
||||||
|
- Add progress tracking and user feedback during sync
|
||||||
|
- Handle sync workflow errors and recovery
|
||||||
|
- _Requirements: 1.1, 1.2, 5.2, 5.3_
|
||||||
|
|
||||||
|
- [ ] 5.2 Implement cleanup functionality for removed events
|
||||||
|
- Create function to identify events in destination not in source
|
||||||
|
- Implement event removal from destination calendar
|
||||||
|
- Add safety checks to prevent accidental deletions
|
||||||
|
- _Requirements: 4.3_
|
||||||
|
|
||||||
|
- [ ] 5.3 Create sync reporting and statistics
|
||||||
|
- Implement sync result tracking (created, updated, removed, skipped)
|
||||||
|
- Create summary display function with detailed results
|
||||||
|
- Add error reporting and logging
|
||||||
|
- _Requirements: 5.3, 5.4_
|
||||||
|
|
||||||
|
- [ ]* 5.4 Write integration tests for sync engine
|
||||||
|
- Test complete sync workflow with test data
|
||||||
|
- Test cleanup functionality accuracy
|
||||||
|
- Test error handling and recovery
|
||||||
|
- _Requirements: 4.3, 5.3_
|
||||||
|
|
||||||
|
- [ ] 6. Implement Logger component
|
||||||
|
- [ ] 6.1 Create logging and progress display functions
|
||||||
|
- Implement message logging with different severity levels
|
||||||
|
- Create progress indicator for sync operations
|
||||||
|
- Add user-friendly error message formatting
|
||||||
|
- _Requirements: 5.1, 5.2, 5.4_
|
||||||
|
|
||||||
|
- [ ] 6.2 Implement sync summary display
|
||||||
|
- Create formatted summary of sync results
|
||||||
|
- Display statistics for events processed
|
||||||
|
- Show any errors or warnings encountered
|
||||||
|
- _Requirements: 5.3, 5.4_
|
||||||
|
|
||||||
|
- [ ] 7. Integrate all components and create main script
|
||||||
|
- [ ] 7.1 Wire together all components in main execution flow
|
||||||
|
- Create main script entry point that calls all components
|
||||||
|
- Implement proper error handling and user feedback flow
|
||||||
|
- Add configuration validation before sync starts
|
||||||
|
- _Requirements: 2.3, 2.4, 5.1_
|
||||||
|
|
||||||
|
- [ ] 7.2 Add user interaction and configuration management
|
||||||
|
- Implement user prompts for calendar selection if needed
|
||||||
|
- Add configuration validation and error messaging
|
||||||
|
- Create user-friendly script execution experience
|
||||||
|
- _Requirements: 2.1, 2.2, 2.3, 2.4_
|
||||||
|
|
||||||
|
- [ ]* 7.3 Create comprehensive end-to-end tests
|
||||||
|
- Test complete sync workflow with real calendar data
|
||||||
|
- Test all error scenarios and edge cases
|
||||||
|
- Validate sync accuracy and cleanup functionality
|
||||||
|
- _Requirements: 1.1, 1.2, 4.3, 5.3_
|
||||||
|
|
||||||
|
- [ ] 8. Finalize and optimize the script
|
||||||
|
- [ ] 8.1 Add performance optimizations and error recovery
|
||||||
|
- Optimize calendar access and event processing performance
|
||||||
|
- Add robust error recovery and rollback capabilities
|
||||||
|
- Implement proper resource cleanup and calendar app management
|
||||||
|
- _Requirements: 5.4_
|
||||||
|
|
||||||
|
- [ ] 8.2 Create user documentation and usage instructions
|
||||||
|
- Write clear instructions for script configuration and usage
|
||||||
|
- Document calendar permission requirements
|
||||||
|
- Create troubleshooting guide for common issues
|
||||||
|
- _Requirements: 2.3, 2.4, 5.4_
|
||||||
165
.kiro/specs/fastpass-additional-control-plane/design.md
Normal file
165
.kiro/specs/fastpass-additional-control-plane/design.md
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# Design Document
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The `fastpass-additional-control-plane` Ansible role will enable the deployment of additional control plane nodes to an existing FastPass Kubernetes cluster. This role follows the established patterns from `fastpass-first-control-plane` but focuses on joining nodes to an already initialized cluster rather than initializing a new one. The role ensures high availability by creating redundant master nodes that can handle API requests, scheduling, and cluster management tasks.
|
||||||
|
|
||||||
|
The key difference from the first control plane role is that this role will use `kubeadm join` with control plane flags instead of `kubeadm init`, and it will need to retrieve join tokens and certificate keys from the existing cluster.
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
### Role Structure
|
||||||
|
The role will follow the standard Ansible role structure:
|
||||||
|
```
|
||||||
|
ansible/playbooks/roles/fastpass-additional-control-plane/
|
||||||
|
├── defaults/
|
||||||
|
│ └── main.yml
|
||||||
|
├── tasks/
|
||||||
|
│ └── main.yml
|
||||||
|
├── handlers/
|
||||||
|
│ └── main.yml (if needed)
|
||||||
|
└── meta/
|
||||||
|
└── main.yml (if needed)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Integration Points
|
||||||
|
- **DNS Management**: Uses the existing `dns-manager` role for consistent DNS record creation
|
||||||
|
- **Kubeconfig Management**: Uses the existing `kubeconfig-manager` role for local kubeconfig setup
|
||||||
|
- **Firewall Configuration**: Reuses firewall service definitions from the first control plane role
|
||||||
|
- **Cluster Integration**: Coordinates with the first control plane node to obtain join credentials
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
- The first control plane node must be fully initialized and running
|
||||||
|
- The `dns-manager` role must be available for DNS record creation
|
||||||
|
- The `kubeconfig-manager` role must be available for kubeconfig setup
|
||||||
|
- Required Kubernetes prerequisites must be installed on target nodes
|
||||||
|
|
||||||
|
## Components and Interfaces
|
||||||
|
|
||||||
|
### Main Task Flow
|
||||||
|
1. **Pre-flight Checks**: Verify cluster readiness and node prerequisites
|
||||||
|
2. **DNS Configuration**: Set up DNS records for the new control plane node
|
||||||
|
3. **Firewall Configuration**: Open required ports for control plane services
|
||||||
|
4. **Kubelet Configuration**: Create initial kubelet configuration
|
||||||
|
5. **Join Token Retrieval**: Get join token and certificate key from first control plane
|
||||||
|
6. **Cluster Join**: Execute kubeadm join with control plane flags
|
||||||
|
7. **Service Management**: Ensure kubelet is enabled and running
|
||||||
|
8. **Kubeconfig Setup**: Configure local kubeconfig access
|
||||||
|
9. **Verification**: Validate successful cluster join
|
||||||
|
|
||||||
|
### Key Variables
|
||||||
|
- `cluster_name`: Name of the Kubernetes cluster
|
||||||
|
- `ip_address`: IP address of the current control plane node
|
||||||
|
- `first_control_plane_host`: Hostname/IP of the first control plane node
|
||||||
|
- `kubernetes_services_control_plane`: List of firewall services to open
|
||||||
|
- `join_token_ttl`: TTL for join tokens (default: 24h)
|
||||||
|
- `certificate_key_ttl`: TTL for certificate keys (default: 2h)
|
||||||
|
|
||||||
|
### External Role Interfaces
|
||||||
|
- **dns-manager**: Provides DNS record creation with `host_name` variable
|
||||||
|
- **kubeconfig-manager**: Handles kubeconfig merging with `cluster_name` variable
|
||||||
|
- **First Control Plane**: Source for join tokens and certificate keys
|
||||||
|
|
||||||
|
## Data Models
|
||||||
|
|
||||||
|
### Join Credentials Structure
|
||||||
|
```yaml
|
||||||
|
join_credentials:
|
||||||
|
token: "abcdef.1234567890abcdef"
|
||||||
|
discovery_token_ca_cert_hash: "sha256:..."
|
||||||
|
certificate_key: "..."
|
||||||
|
api_server_endpoint: "cluster-name:6443"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Firewall Services
|
||||||
|
```yaml
|
||||||
|
kubernetes_services_control_plane:
|
||||||
|
- kubernetes_API # Port 6443
|
||||||
|
- etcd # Ports 2379-2380
|
||||||
|
- kubelet # Port 10250
|
||||||
|
- kube-scheduler # Port 10259
|
||||||
|
- kube-controller-manager # Port 10257
|
||||||
|
```
|
||||||
|
|
||||||
|
### Node Status Tracking
|
||||||
|
```yaml
|
||||||
|
node_status:
|
||||||
|
joined: false
|
||||||
|
kubelet_running: false
|
||||||
|
dns_configured: false
|
||||||
|
kubeconfig_ready: false
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Join Token Management
|
||||||
|
- **Token Expiration**: Automatically generate new tokens if existing ones are expired
|
||||||
|
- **Certificate Key Rotation**: Handle certificate key expiration gracefully
|
||||||
|
- **Network Connectivity**: Retry join operations with exponential backoff
|
||||||
|
- **API Server Availability**: Wait for API server readiness before attempting join
|
||||||
|
|
||||||
|
### Idempotency Checks
|
||||||
|
- **Already Joined Nodes**: Skip join process if node is already part of the cluster
|
||||||
|
- **Existing Configuration**: Preserve existing kubelet configuration if valid
|
||||||
|
- **DNS Records**: Update existing DNS records instead of creating duplicates
|
||||||
|
- **Service Status**: Only restart services if configuration changes
|
||||||
|
|
||||||
|
### Failure Recovery
|
||||||
|
- **Partial Join Failures**: Clean up partial configurations and retry
|
||||||
|
- **Network Issues**: Provide clear error messages for connectivity problems
|
||||||
|
- **Permission Errors**: Validate sudo/root access before attempting operations
|
||||||
|
- **Resource Constraints**: Check system resources before proceeding
|
||||||
|
|
||||||
|
## Testing Strategy
|
||||||
|
|
||||||
|
### Unit Testing Approach
|
||||||
|
- **Task Validation**: Test individual tasks with mock data
|
||||||
|
- **Variable Validation**: Ensure required variables are properly defined
|
||||||
|
- **Conditional Logic**: Test all conditional branches in tasks
|
||||||
|
- **Error Scenarios**: Validate error handling for common failure cases
|
||||||
|
|
||||||
|
### Integration Testing
|
||||||
|
- **Multi-Node Clusters**: Test with 3 and 5 control plane node configurations
|
||||||
|
- **Network Scenarios**: Test across different network topologies
|
||||||
|
- **OS Compatibility**: Validate on supported operating systems (Ubuntu/Debian)
|
||||||
|
- **Version Compatibility**: Test with different Kubernetes versions
|
||||||
|
|
||||||
|
### Validation Checks
|
||||||
|
- **Cluster Health**: Verify all control plane nodes are healthy after join
|
||||||
|
- **API Availability**: Confirm API server is accessible from all nodes
|
||||||
|
- **Etcd Cluster**: Validate etcd cluster membership and health
|
||||||
|
- **Scheduling**: Test pod scheduling across all control plane nodes
|
||||||
|
- **Failover**: Verify cluster continues operating if one control plane fails
|
||||||
|
|
||||||
|
### Test Scenarios
|
||||||
|
1. **Fresh Join**: Join additional control plane to newly created cluster
|
||||||
|
2. **Existing Cluster**: Add control plane to cluster with existing workloads
|
||||||
|
3. **Network Partitions**: Test behavior during temporary network issues
|
||||||
|
4. **Token Expiration**: Handle expired join tokens gracefully
|
||||||
|
5. **Retry Operations**: Validate retry logic for transient failures
|
||||||
|
|
||||||
|
## Implementation Considerations
|
||||||
|
|
||||||
|
### Security
|
||||||
|
- **Token Security**: Ensure join tokens are handled securely and not logged
|
||||||
|
- **Certificate Management**: Properly manage and rotate certificate keys
|
||||||
|
- **Network Security**: Validate firewall rules don't expose unnecessary ports
|
||||||
|
- **Access Control**: Ensure proper RBAC is maintained after node joins
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- **Parallel Execution**: Support joining multiple control plane nodes simultaneously
|
||||||
|
- **Resource Usage**: Monitor CPU and memory usage during join process
|
||||||
|
- **Network Bandwidth**: Optimize data transfer during cluster join
|
||||||
|
- **Startup Time**: Minimize time to achieve cluster readiness
|
||||||
|
|
||||||
|
### Monitoring and Observability
|
||||||
|
- **Join Progress**: Provide clear progress indicators during join process
|
||||||
|
- **Health Checks**: Implement comprehensive health validation
|
||||||
|
- **Logging**: Ensure adequate logging for troubleshooting
|
||||||
|
- **Metrics**: Expose relevant metrics for monitoring cluster growth
|
||||||
|
|
||||||
|
### Compatibility
|
||||||
|
- **Kubernetes Versions**: Support current and previous Kubernetes versions
|
||||||
|
- **Operating Systems**: Maintain compatibility with Ubuntu and Debian
|
||||||
|
- **Container Runtimes**: Work with containerd runtime configuration
|
||||||
|
- **Network Plugins**: Compatible with Flannel CNI configuration
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
# Requirements Document
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
This feature involves creating an Ansible role called `fastpass-additional-control-plane` that will deploy additional control plane nodes to an existing FastPass Kubernetes cluster. The role will follow the same pattern as the existing `fastpass-first-control-plane` role but will focus on joining nodes to an already initialized cluster rather than initializing a new cluster. This ensures high availability for the Kubernetes control plane by adding redundant master nodes.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement 1
|
||||||
|
|
||||||
|
**User Story:** As a DevOps engineer, I want to deploy additional control plane nodes to my FastPass Kubernetes cluster, so that I can achieve high availability and fault tolerance for the cluster control plane.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the role is executed on a node THEN the system SHALL join the node to the existing Kubernetes cluster as a control plane node
|
||||||
|
2. WHEN the role runs THEN the system SHALL configure the necessary firewall rules for control plane services
|
||||||
|
3. WHEN the role executes THEN the system SHALL ensure the kubelet service is properly configured and running
|
||||||
|
4. WHEN joining the cluster THEN the system SHALL use the correct join token and certificate key from the first control plane node
|
||||||
|
5. WHEN the role completes THEN the system SHALL verify the node has successfully joined as a control plane node
|
||||||
|
|
||||||
|
### Requirement 2
|
||||||
|
|
||||||
|
**User Story:** As a system administrator, I want the additional control plane role to follow the same patterns as the first control plane role, so that the codebase remains consistent and maintainable.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the role is created THEN the system SHALL follow the same directory structure as fastpass-first-control-plane
|
||||||
|
2. WHEN the role is implemented THEN the system SHALL use similar variable naming conventions and task organization
|
||||||
|
3. WHEN the role runs THEN the system SHALL include proper error handling and idempotency checks
|
||||||
|
4. WHEN the role executes THEN the system SHALL use the same firewall service definitions as the first control plane role
|
||||||
|
5. WHEN the role is documented THEN the system SHALL include proper metadata headers with author, version, and description
|
||||||
|
|
||||||
|
### Requirement 3
|
||||||
|
|
||||||
|
**User Story:** As a cluster operator, I want the additional control plane nodes to have proper DNS configuration, so that they can be reached by their cluster names and participate in load balancing.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the role runs THEN the system SHALL configure DNS records for the additional control plane nodes
|
||||||
|
2. WHEN DNS is configured THEN the system SHALL use the dns-manager role for consistency
|
||||||
|
3. WHEN the role executes THEN the system SHALL ensure the node can resolve the cluster endpoint
|
||||||
|
4. WHEN DNS setup completes THEN the system SHALL verify connectivity to the cluster API endpoint
|
||||||
|
|
||||||
|
### Requirement 4
|
||||||
|
|
||||||
|
**User Story:** As a DevOps engineer, I want the role to handle kubeconfig management for additional control plane nodes, so that I can manage the cluster from any control plane node.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the role completes THEN the system SHALL configure kubeconfig for the new control plane node
|
||||||
|
2. WHEN kubeconfig is set up THEN the system SHALL use the kubeconfig-manager role for consistency
|
||||||
|
3. WHEN the role runs THEN the system SHALL ensure proper permissions are set on kubeconfig files
|
||||||
|
4. WHEN kubeconfig is configured THEN the system SHALL verify kubectl access works from the new node
|
||||||
|
|
||||||
|
### Requirement 5
|
||||||
|
|
||||||
|
**User Story:** As a system administrator, I want the role to be idempotent and handle edge cases, so that I can run it multiple times safely without causing issues.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the role is run multiple times THEN the system SHALL not attempt to rejoin an already joined node
|
||||||
|
2. WHEN a node is already part of the cluster THEN the system SHALL skip the join process gracefully
|
||||||
|
3. WHEN the role encounters errors THEN the system SHALL provide clear error messages and fail gracefully
|
||||||
|
4. WHEN prerequisites are missing THEN the system SHALL report what needs to be configured first
|
||||||
|
5. WHEN the role runs THEN the system SHALL validate that required variables are defined
|
||||||
|
|
||||||
|
### Requirement 6
|
||||||
|
|
||||||
|
**User Story:** As a cluster administrator, I want the role to integrate seamlessly with the existing FastPass deployment workflow, so that it can be used in the 4-step deployment process.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the role is created THEN the system SHALL be compatible with the deploy-fastpass-4step.yml playbook
|
||||||
|
2. WHEN the role runs THEN the system SHALL work with the fastpass_control_plane[1:] host group
|
||||||
|
3. WHEN integrated THEN the system SHALL not interfere with the first control plane initialization
|
||||||
|
4. WHEN the role executes THEN the system SHALL depend on the first control plane node being ready
|
||||||
|
5. WHEN deployment completes THEN the system SHALL allow worker nodes to join the cluster successfully
|
||||||
118
.kiro/specs/fastpass-additional-control-plane/tasks.md
Normal file
118
.kiro/specs/fastpass-additional-control-plane/tasks.md
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
# Implementation Plan
|
||||||
|
|
||||||
|
- [ ] 1. Create role directory structure and basic configuration
|
||||||
|
- Create the fastpass-additional-control-plane role directory structure
|
||||||
|
- Set up defaults/main.yml with required variables and firewall services
|
||||||
|
- Create meta/main.yml with role metadata and dependencies
|
||||||
|
- _Requirements: 2.1, 2.2, 2.4_
|
||||||
|
|
||||||
|
- [ ] 2. Implement join token and certificate key retrieval
|
||||||
|
- [ ] 2.1 Create tasks to generate new join tokens from first control plane
|
||||||
|
- Write Ansible tasks to execute kubeadm token create on first control plane node
|
||||||
|
- Implement token validation and expiration checking
|
||||||
|
- Add error handling for token generation failures
|
||||||
|
- _Requirements: 1.4, 5.4_
|
||||||
|
|
||||||
|
- [ ] 2.2 Implement certificate key retrieval and management
|
||||||
|
- Create tasks to upload and retrieve certificate keys from first control plane
|
||||||
|
- Add certificate key expiration handling and rotation
|
||||||
|
- Implement secure handling of certificate keys in variables
|
||||||
|
- _Requirements: 1.4, 5.1_
|
||||||
|
|
||||||
|
- [ ] 2.3 Create discovery token CA certificate hash retrieval
|
||||||
|
- Write tasks to extract CA certificate hash from first control plane
|
||||||
|
- Implement validation of certificate hash format
|
||||||
|
- Add error handling for certificate retrieval failures
|
||||||
|
- _Requirements: 1.4, 5.4_
|
||||||
|
|
||||||
|
- [ ] 3. Implement DNS configuration and firewall setup
|
||||||
|
- [ ] 3.1 Configure DNS records for additional control plane nodes
|
||||||
|
- Integrate dns-manager role for consistent DNS record creation
|
||||||
|
- Pass appropriate host_name variable to dns-manager
|
||||||
|
- Add DNS propagation wait and validation
|
||||||
|
- _Requirements: 3.1, 3.2, 3.4_
|
||||||
|
|
||||||
|
- [ ] 3.2 Set up firewall rules for control plane services
|
||||||
|
- Reuse kubernetes_services_control_plane from defaults
|
||||||
|
- Implement UFW firewall rule creation for Debian/Ubuntu systems
|
||||||
|
- Add conditional logic for different operating systems
|
||||||
|
- _Requirements: 1.2, 2.4_
|
||||||
|
|
||||||
|
- [ ] 4. Implement kubelet configuration and cluster join
|
||||||
|
- [ ] 4.1 Create initial kubelet configuration
|
||||||
|
- Write kubelet config.yaml with systemd cgroup driver
|
||||||
|
- Set containerd socket endpoint configuration
|
||||||
|
- Ensure proper file permissions and ownership
|
||||||
|
- _Requirements: 1.3, 2.3_
|
||||||
|
|
||||||
|
- [ ] 4.2 Execute kubeadm join for control plane
|
||||||
|
- Implement kubeadm join command with control-plane flag
|
||||||
|
- Use retrieved join token, certificate key, and CA cert hash
|
||||||
|
- Add proper command argument construction and validation
|
||||||
|
- Include idempotency checks to prevent duplicate joins
|
||||||
|
- _Requirements: 1.1, 1.4, 5.1, 5.2_
|
||||||
|
|
||||||
|
- [ ] 4.3 Ensure kubelet service management
|
||||||
|
- Enable and start kubelet systemd service
|
||||||
|
- Add service status validation and error handling
|
||||||
|
- Implement service restart logic if needed
|
||||||
|
- _Requirements: 1.3, 1.5_
|
||||||
|
|
||||||
|
- [ ] 5. Implement kubeconfig management and validation
|
||||||
|
- [ ] 5.1 Configure kubeconfig for additional control plane nodes
|
||||||
|
- Integrate kubeconfig-manager role for consistent configuration
|
||||||
|
- Pass cluster_name variable to kubeconfig-manager
|
||||||
|
- Ensure proper kubeconfig merging with existing configurations
|
||||||
|
- _Requirements: 4.1, 4.2, 4.3_
|
||||||
|
|
||||||
|
- [ ] 5.2 Implement cluster join validation
|
||||||
|
- Create tasks to verify node successfully joined as control plane
|
||||||
|
- Add kubectl commands to check node status and roles
|
||||||
|
- Implement cluster health validation checks
|
||||||
|
- _Requirements: 1.5, 4.4_
|
||||||
|
|
||||||
|
- [ ] 6. Add comprehensive error handling and idempotency
|
||||||
|
- [ ] 6.1 Implement pre-flight validation checks
|
||||||
|
- Check if node is already joined to cluster
|
||||||
|
- Validate required variables are defined
|
||||||
|
- Verify first control plane node accessibility
|
||||||
|
- Add system resource and prerequisite checks
|
||||||
|
- _Requirements: 5.1, 5.2, 5.4, 5.5_
|
||||||
|
|
||||||
|
- [ ] 6.2 Add retry logic and failure recovery
|
||||||
|
- Implement retry mechanisms for transient failures
|
||||||
|
- Add exponential backoff for network-related operations
|
||||||
|
- Create cleanup tasks for partial join failures
|
||||||
|
- _Requirements: 5.3, 5.4_
|
||||||
|
|
||||||
|
- [ ] 7. Integration with FastPass deployment workflow
|
||||||
|
- [ ] 7.1 Ensure compatibility with deploy-fastpass-4step.yml
|
||||||
|
- Verify role works with fastpass_control_plane[1:] host group
|
||||||
|
- Test integration with existing playbook structure
|
||||||
|
- Validate dependency on first control plane completion
|
||||||
|
- _Requirements: 6.1, 6.2, 6.3, 6.4_
|
||||||
|
|
||||||
|
- [ ] 7.2 Add proper task documentation and metadata
|
||||||
|
- Include role header with author, version, and description
|
||||||
|
- Add inline comments for complex task logic
|
||||||
|
- Document required variables and their purposes
|
||||||
|
- _Requirements: 2.2, 2.5_
|
||||||
|
|
||||||
|
- [ ]* 8. Create comprehensive testing and validation
|
||||||
|
- [ ]* 8.1 Write unit tests for individual tasks
|
||||||
|
- Create test cases for token retrieval logic
|
||||||
|
- Test kubeadm join command construction
|
||||||
|
- Validate error handling scenarios
|
||||||
|
- _Requirements: 1.1, 1.4, 5.1_
|
||||||
|
|
||||||
|
- [ ]* 8.2 Implement integration tests
|
||||||
|
- Test multi-node control plane deployment
|
||||||
|
- Validate cluster health after additional nodes join
|
||||||
|
- Test failover scenarios and cluster resilience
|
||||||
|
- _Requirements: 1.5, 6.5_
|
||||||
|
|
||||||
|
- [ ]* 8.3 Add validation scripts and health checks
|
||||||
|
- Create scripts to verify cluster state after deployment
|
||||||
|
- Implement automated health validation
|
||||||
|
- Add performance and resource usage monitoring
|
||||||
|
- _Requirements: 1.5, 4.4_
|
||||||
51
.kiro/specs/fastpass-dns-loadbalancer-fix/requirements.md
Normal file
51
.kiro/specs/fastpass-dns-loadbalancer-fix/requirements.md
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# Requirements Document
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
The FastPass Kubernetes cluster deployment currently has critical DNS and load balancing configuration issues that prevent proper high availability setup. While the cluster endpoint `fastpass.local.mk-labs.cloud` is defined in the group variables, the `cluster_vip` variable required by the DNS manager role is missing, and the Traefik load balancer configuration is commented out. This means the cluster endpoint cannot resolve properly and there's no load balancing for the control plane API. This feature will fix these configuration gaps to enable true HA functionality.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
### Requirement 1: DNS CNAME Record for Load Balancer
|
||||||
|
|
||||||
|
**User Story:** As a DevOps engineer, I want the DNS manager to create a CNAME record for the cluster endpoint pointing to the load balancer, so that the cluster endpoint resolves through the load balancer rather than directly to node IPs.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the dns-manager role is called for a load-balanced cluster THEN the system SHALL create a CNAME record instead of an A record
|
||||||
|
2. WHEN the CNAME record is created THEN the system SHALL point fastpass.local.mk-labs.cloud to the traefik_server (lightning_lane.local.mk-labs.cloud)
|
||||||
|
3. WHEN the DNS record type is determined THEN the system SHALL use CNAME for load-balanced endpoints and A records for direct node access
|
||||||
|
4. WHEN DNS propagation occurs THEN the system SHALL verify that the CNAME resolution works correctly
|
||||||
|
|
||||||
|
### Requirement 2: Complete Traefik Integration
|
||||||
|
|
||||||
|
**User Story:** As a DevOps engineer, I want the Traefik load balancer to be fully integrated with the FastPass deployment, so that the cluster VIP is properly load balanced across all control plane nodes.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the traefik-manager role is called THEN the system SHALL use the traefik_server variable (lightning_lane) as the target host
|
||||||
|
2. WHEN Traefik configuration is generated THEN the system SHALL create proper TCP routing for the cluster endpoint to all control plane nodes
|
||||||
|
3. WHEN the cluster VIP is accessed THEN the system SHALL distribute requests across space-mountain, big-thunder-mountain, and splash-mountain
|
||||||
|
4. WHEN Traefik configuration is applied THEN the system SHALL reload the Traefik service to activate the new configuration
|
||||||
|
|
||||||
|
### Requirement 3: High Availability Validation
|
||||||
|
|
||||||
|
**User Story:** As a DevOps engineer, I want to validate that the HA setup is working correctly, so that I can be confident the cluster will survive node failures.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN the deployment completes THEN the system SHALL test connectivity to the cluster endpoint
|
||||||
|
2. WHEN connectivity tests run THEN the system SHALL verify that the endpoint resolves through the CNAME to the load balancer
|
||||||
|
3. WHEN load balancer tests run THEN the system SHALL verify that requests are being distributed across control plane nodes
|
||||||
|
4. WHEN a control plane node is stopped THEN the system SHALL continue to serve API requests through the remaining nodes
|
||||||
|
|
||||||
|
### Requirement 4: Backward Compatibility
|
||||||
|
|
||||||
|
**User Story:** As a DevOps engineer, I want the DNS fixes to be backward compatible with existing deployments, so that current clusters continue to function during the transition.
|
||||||
|
|
||||||
|
#### Acceptance Criteria
|
||||||
|
|
||||||
|
1. WHEN existing clusters are updated THEN the system SHALL not break existing DNS configurations
|
||||||
|
2. WHEN new variables are introduced THEN the system SHALL provide sensible defaults for existing deployments
|
||||||
|
3. WHEN the update is applied THEN the system SHALL preserve existing kubeconfig files and cluster access
|
||||||
|
4. IF migration issues occur THEN the system SHALL provide rollback procedures and documentation
|
||||||
27
README.md
27
README.md
@@ -6,11 +6,9 @@ This implementation is built on easily accessible consumer based hardware and wi
|
|||||||
|
|
||||||
## 🎯 Project Goals
|
## 🎯 Project Goals
|
||||||
|
|
||||||
- **Multi-cluster OpenShift management** with ACM
|
- **Kubernetes cluster for applications**
|
||||||
- **Hybrid cloud scenarios** (bare metal + virtualized + containerized)
|
- **IAM integration testing**
|
||||||
- **Enterprise integration testing** (AD, SQL Server, SIEM)
|
|
||||||
- **GitOps and automation workflows**
|
- **GitOps and automation workflows**
|
||||||
- **Red Hat certification preparation**
|
|
||||||
|
|
||||||
## 📋 Documentation (Priority Order)
|
## 📋 Documentation (Priority Order)
|
||||||
|
|
||||||
@@ -25,18 +23,18 @@ This implementation is built on easily accessible consumer based hardware and wi
|
|||||||
6. **[VM Templates & Automation](./docs/13-vm-automation.md)** *(TBD)* - Template creation
|
6. **[VM Templates & Automation](./docs/13-vm-automation.md)** *(TBD)* - Template creation
|
||||||
|
|
||||||
### Phase 3: Infrastructure Services
|
### Phase 3: Infrastructure Services
|
||||||
7. **[Recursive DNS](./docs/09-openshift-sno.md)** *(TBD)* - ACM Hub Cluster
|
7. **[Recursive DNS]
|
||||||
8. **[Authoritative DNS](./docs/08-openshift-compact.md)** *(TBD)* - 3 Master/3 Worker node (production-like)
|
8. **[Authoritative DNS]
|
||||||
9. **[Identity Management](./docs/10-acm-setup.md)** *(TBD)* - Multi-cluster management
|
9. **[Identity Management](./docs/10-acm-setup.md)** *(TBD)*
|
||||||
10. **[Matchbox](./docs/10-acm-setup.md)** *(TBD)* - External app cluster
|
10. **[Matchbox] (Depreciated?)
|
||||||
|
|
||||||
### Phase 4: OpenShift Clusters
|
### Phase 4: OpenShift Clusters (Depreciated)
|
||||||
8. **[OpenShift SNO + Worker](./docs/09-openshift-sno.md)** *(TBD)* - ACM Hub Cluster
|
8. **[OpenShift SNO + Worker](./docs/09-openshift-sno.md)** *(TBD)* - ACM Hub Cluster
|
||||||
9. **[OpenShift Cluster](./docs/08-openshift-compact.md)** *(TBD)* - 3 Master/3 Worker node (production-like)
|
9. **[OpenShift Cluster](./docs/08-openshift-compact.md)** *(TBD)* - 3 Master/3 Worker node (production-like)
|
||||||
10. **[ACM Configuration](./docs/10-acm-setup.md)** *(TBD)* - Multi-cluster management
|
10. **[ACM Configuration](./docs/10-acm-setup.md)** *(TBD)* - Multi-cluster management
|
||||||
11. **[HCP Cluster](./docs/10-acm-setup.md)** *(TBD)* - External app cluster
|
11. **[HCP Cluster](./docs/10-acm-setup.md)** *(TBD)* - External app cluster
|
||||||
|
|
||||||
### Phase 5: Container Platform
|
### Phase 5: Kubernetes Container Platform
|
||||||
5. **[Container Registry Setup](./docs/05-container-registry.md)** *(TBD)* - Harbor deployment
|
5. **[Container Registry Setup](./docs/05-container-registry.md)** *(TBD)* - Harbor deployment
|
||||||
6. **[Git Repository Setup](./docs/06-git-repository.md)** *(TBD)* - Gitea/GitLab on Synology
|
6. **[Git Repository Setup](./docs/06-git-repository.md)** *(TBD)* - Gitea/GitLab on Synology
|
||||||
7. **[Artifact Repository](./docs/07-artifact-repository.md)** *(TBD)* - Nexus/Artifactory
|
7. **[Artifact Repository](./docs/07-artifact-repository.md)** *(TBD)* - Nexus/Artifactory
|
||||||
@@ -99,14 +97,13 @@ configurations
|
|||||||
## 🔧 Technology Stack
|
## 🔧 Technology Stack
|
||||||
|
|
||||||
### Infrastructure
|
### Infrastructure
|
||||||
- **Networking**: Ubiquiti UDM SE
|
- **Networking**: Ubiquiti UDM Pro
|
||||||
- **Storage**: Synology DS1621+, Ubiquiti UNAS Pro
|
- **Storage**: Synology DS1621+, Ubiquiti UNAS Pro
|
||||||
- **Compute**: 3x Beelink S12 Pro, 5x Lenovo M710q, Dell T640
|
- **Compute**: 3x Minisforum TH60, 2x Minisforum MS01, 7x Dell 7050 SFF
|
||||||
|
|
||||||
### Container Platforms
|
### Container Platforms
|
||||||
- **OpenShift 4.14+**: Two clusters (compact + SNO)
|
- **k8s**: Core services cluster
|
||||||
- **k0s**: Core services cluster
|
- **Proxmox**: VM workloads
|
||||||
- **vSphere**: VM workloads
|
|
||||||
|
|
||||||
### Core Services
|
### Core Services
|
||||||
- **Container Registry**: Harbor
|
- **Container Registry**: Harbor
|
||||||
|
|||||||
193
ansible/DNS_MANAGEMENT_REFACTOR.md
Normal file
193
ansible/DNS_MANAGEMENT_REFACTOR.md
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
# DNS Management Refactor - Modular & Repeatable
|
||||||
|
|
||||||
|
This document explains the refactoring of DNS management from standalone playbooks to modular, reusable tasks.
|
||||||
|
|
||||||
|
## 🎯 **What Changed**
|
||||||
|
|
||||||
|
### **Before (Monolithic)**
|
||||||
|
```yaml
|
||||||
|
# Standalone playbook: add_technitium_dns_entry.yml
|
||||||
|
- name: Add entry to Technitium DNS
|
||||||
|
hosts: all
|
||||||
|
tasks:
|
||||||
|
- name: Create DNS entry
|
||||||
|
effectivelywild.technitium_dns.technitium_dns_add_record:
|
||||||
|
# ... hardcoded parameters
|
||||||
|
```
|
||||||
|
|
||||||
|
### **After (Modular)**
|
||||||
|
```yaml
|
||||||
|
# Reusable task: tasks/add_technitium_dns_entry.yml
|
||||||
|
- name: Create DNS entry for {{ dns_record_name }}
|
||||||
|
effectivelywild.technitium_dns.technitium_dns_add_record:
|
||||||
|
# ... parameterized with variables
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📁 **New Structure**
|
||||||
|
|
||||||
|
```
|
||||||
|
ansible/
|
||||||
|
├── playbooks/
|
||||||
|
│ ├── tasks/
|
||||||
|
│ │ └── add_technitium_dns_entry.yml # ✅ Reusable task file
|
||||||
|
│ ├── add_dns_entry.yml # ✅ New playbook using task
|
||||||
|
│ ├── add_technitium_dns_entry.yml.backup # 📦 Backed up old version
|
||||||
|
│ └── roles/
|
||||||
|
│ └── dns-manager/ # ✅ Enhanced role
|
||||||
|
│ ├── tasks/main.yml # Uses task file
|
||||||
|
│ └── defaults/main.yml # Technitium defaults
|
||||||
|
└── scripts/
|
||||||
|
└── migrate-dns-references.sh # ✅ Migration helper
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 **Usage Examples**
|
||||||
|
|
||||||
|
### **1. In Playbooks (Direct Task Include)**
|
||||||
|
```yaml
|
||||||
|
- name: Add DNS entry for my server
|
||||||
|
hosts: my_servers
|
||||||
|
tasks:
|
||||||
|
- name: Create DNS entry
|
||||||
|
ansible.builtin.include_tasks: tasks/add_technitium_dns_entry.yml
|
||||||
|
vars:
|
||||||
|
dns_record_name: "{{ inventory_hostname }}"
|
||||||
|
dns_zone: "{{ base_domain }}"
|
||||||
|
dns_ip_address: "{{ ansible_default_ipv4.address }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
### **2. Using the DNS Manager Role**
|
||||||
|
```yaml
|
||||||
|
- name: Setup cluster DNS
|
||||||
|
hosts: control_plane[0]
|
||||||
|
roles:
|
||||||
|
- role: dns-manager
|
||||||
|
vars:
|
||||||
|
cluster_endpoint: "my-cluster.local.mk-labs.cloud"
|
||||||
|
cluster_vip: "10.1.71.100"
|
||||||
|
```
|
||||||
|
|
||||||
|
### **3. Using the New Playbook**
|
||||||
|
```yaml
|
||||||
|
# Import the new modular playbook
|
||||||
|
- import_playbook: add_dns_entry.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### **4. In Cluster Network Setup**
|
||||||
|
```yaml
|
||||||
|
- name: Setup complete cluster network
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: cluster-network-setup
|
||||||
|
vars:
|
||||||
|
cluster_name: "fastpass"
|
||||||
|
cluster_endpoint: "fastpass.local.mk-labs.cloud"
|
||||||
|
cluster_vip: "10.1.71.53"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 **Migration Guide**
|
||||||
|
|
||||||
|
### **Automatic Migration**
|
||||||
|
```bash
|
||||||
|
# Run the migration script to find references
|
||||||
|
./scripts/migrate-dns-references.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
### **Manual Updates**
|
||||||
|
|
||||||
|
1. **Replace playbook imports:**
|
||||||
|
```yaml
|
||||||
|
# OLD
|
||||||
|
- import_playbook: add_technitium_dns_entry.yml
|
||||||
|
|
||||||
|
# NEW
|
||||||
|
- import_playbook: add_dns_entry.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Use task includes in roles:**
|
||||||
|
```yaml
|
||||||
|
- ansible.builtin.include_tasks: tasks/add_technitium_dns_entry.yml
|
||||||
|
vars:
|
||||||
|
dns_record_name: "my-server"
|
||||||
|
dns_ip_address: "10.1.71.100"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Use the dns-manager role:**
|
||||||
|
```yaml
|
||||||
|
- ansible.builtin.include_role:
|
||||||
|
name: dns-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 **Variable Reference**
|
||||||
|
|
||||||
|
### **Task Variables (`tasks/add_technitium_dns_entry.yml`)**
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `dns_record_name` | `inventory_hostname` | DNS record name |
|
||||||
|
| `dns_zone` | `base_domain` | DNS zone |
|
||||||
|
| `dns_ip_address` | `ip_address` | IP address for A record |
|
||||||
|
| `dns_record_type` | `A` | DNS record type |
|
||||||
|
| `dns_ttl` | `360` | TTL in seconds |
|
||||||
|
| `dns_create_ptr` | `true` | Create PTR record |
|
||||||
|
| `dns_debug` | `true` | Show debug output |
|
||||||
|
|
||||||
|
### **DNS Manager Role Variables**
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `cluster_endpoint` | - | Full cluster FQDN |
|
||||||
|
| `cluster_vip` | - | Cluster VIP address |
|
||||||
|
| `dns_management_enabled` | `true` | Enable DNS management |
|
||||||
|
| `use_hosts_file_fallback` | `true` | Add to /etc/hosts |
|
||||||
|
| `dns_ttl` | `360` | DNS TTL |
|
||||||
|
| `create_ptr_record` | `true` | Create PTR record |
|
||||||
|
|
||||||
|
## 🎯 **Benefits**
|
||||||
|
|
||||||
|
### ✅ **Modularity**
|
||||||
|
- Single task file used across multiple contexts
|
||||||
|
- Consistent DNS management approach
|
||||||
|
- Easy to maintain and update
|
||||||
|
|
||||||
|
### ✅ **Flexibility**
|
||||||
|
- Works in playbooks, roles, and standalone
|
||||||
|
- Parameterized for different use cases
|
||||||
|
- Supports multiple DNS providers (extensible)
|
||||||
|
|
||||||
|
### ✅ **Maintainability**
|
||||||
|
- One place to update DNS logic
|
||||||
|
- Clear variable interface
|
||||||
|
- Better error handling and debugging
|
||||||
|
|
||||||
|
### ✅ **Integration**
|
||||||
|
- Seamlessly integrates with cluster setup
|
||||||
|
- Works with existing homelab infrastructure
|
||||||
|
- Compatible with Traefik load balancer setup
|
||||||
|
|
||||||
|
## 🔄 **Integration with Cluster Setup**
|
||||||
|
|
||||||
|
The DNS management now integrates seamlessly with your cluster deployment:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# In fastpass-first-control-plane role
|
||||||
|
- name: Setup network infrastructure for FastPass cluster
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: cluster-network-setup
|
||||||
|
vars:
|
||||||
|
cluster_name: "{{ cluster_name }}"
|
||||||
|
cluster_endpoint: "{{ control_plane_endpoint }}"
|
||||||
|
cluster_vip: "{{ ansible_default_ipv4.address }}"
|
||||||
|
control_plane_nodes: "{{ groups['fastpass_control_plane'] }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
This automatically:
|
||||||
|
1. ✅ Creates DNS entry for `fastpass.local.mk-labs.cloud`
|
||||||
|
2. ✅ Configures Traefik load balancer
|
||||||
|
3. ✅ Tests connectivity
|
||||||
|
4. ✅ Provides fallback to /etc/hosts
|
||||||
|
|
||||||
|
## 🚀 **Next Steps**
|
||||||
|
|
||||||
|
1. **Test the refactored approach** with your FastPass cluster
|
||||||
|
2. **Extend to other clusters** (Hub, Internal) using the same pattern
|
||||||
|
3. **Add support for other DNS providers** if needed
|
||||||
|
4. **Create monitoring** for DNS health checks
|
||||||
|
|
||||||
|
This modular approach makes your homelab's DNS management much more maintainable and repeatable across all your Kubernetes clusters!
|
||||||
233
ansible/KUBECONFIG_MANAGEMENT.md
Normal file
233
ansible/KUBECONFIG_MANAGEMENT.md
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
# Kubeconfig Management - Modular & Repeatable
|
||||||
|
|
||||||
|
This document explains the modular kubeconfig management system for your homelab's multiple Kubernetes clusters.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The kubeconfig management has been refactored into reusable, modular components that can handle multiple clusters seamlessly:
|
||||||
|
|
||||||
|
- **FastPass** (Vanilla Kubernetes)
|
||||||
|
- **Hub Cluster** (OpenShift SNO)
|
||||||
|
- **Internal Cluster** (OpenShift)
|
||||||
|
- **Future clusters** (easily extensible)
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
ansible/playbooks/roles/
|
||||||
|
├── kubeconfig-manager/ # Core reusable role
|
||||||
|
│ ├── tasks/main.yml # Main entry point
|
||||||
|
│ ├── tasks/merge-kubeconfig.yml # Merging logic
|
||||||
|
│ ├── defaults/main.yml # Default variables
|
||||||
|
│ └── README.md # Role documentation
|
||||||
|
├── cluster-kubeconfig/ # Generic wrapper role
|
||||||
|
└── fastpass-first-control-plane/ # Uses kubeconfig-manager
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quick Usage
|
||||||
|
|
||||||
|
### 1. Using the Script (Easiest)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ansible
|
||||||
|
|
||||||
|
# Setup FastPass cluster kubeconfig
|
||||||
|
./scripts/setup-kubeconfig.sh fastpass fastpass_control_plane[0]
|
||||||
|
|
||||||
|
# Setup Hub cluster kubeconfig
|
||||||
|
./scripts/setup-kubeconfig.sh hub hub_cluster
|
||||||
|
|
||||||
|
# Setup Internal cluster kubeconfig
|
||||||
|
./scripts/setup-kubeconfig.sh internal internal_cluster[0]
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Direct Ansible Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Single cluster
|
||||||
|
ansible-playbook -i inventory.yml \
|
||||||
|
playbooks/examples/multi-cluster-kubeconfig.yml \
|
||||||
|
--limit fastpass_control_plane[0] \
|
||||||
|
-e target_cluster_name=fastpass
|
||||||
|
|
||||||
|
# Multiple clusters at once
|
||||||
|
ansible-playbook -i inventory.yml \
|
||||||
|
playbooks/examples/multi-cluster-kubeconfig.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. In Your Own Playbooks
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Setup kubeconfig for any cluster
|
||||||
|
hosts: my_cluster_nodes[0]
|
||||||
|
roles:
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "my-cluster"
|
||||||
|
kubeconfig_source_path: "/etc/kubernetes/admin.conf"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### ✅ **Modular & Reusable**
|
||||||
|
- Single role works with any Kubernetes cluster
|
||||||
|
- Easy to extend for new clusters
|
||||||
|
- Consistent behavior across all clusters
|
||||||
|
|
||||||
|
### ✅ **Safe Operations**
|
||||||
|
- Automatic backups before merging
|
||||||
|
- Non-destructive merging
|
||||||
|
- Preserves existing contexts
|
||||||
|
|
||||||
|
### ✅ **Multi-Cluster Ready**
|
||||||
|
- Unique naming: `cluster-name-admin`
|
||||||
|
- No conflicts between clusters
|
||||||
|
- Easy context switching
|
||||||
|
|
||||||
|
### ✅ **Homelab Optimized**
|
||||||
|
- Works with vanilla Kubernetes
|
||||||
|
- Works with OpenShift
|
||||||
|
- Handles different kubeconfig paths
|
||||||
|
|
||||||
|
## Generated Structure
|
||||||
|
|
||||||
|
After running the kubeconfig management:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
~/.kube/
|
||||||
|
├── config # Merged config with all clusters
|
||||||
|
├── config-fastpass # Individual cluster configs
|
||||||
|
├── config-hub
|
||||||
|
├── config-internal
|
||||||
|
└── config.backup.1697123456 # Timestamped backups
|
||||||
|
```
|
||||||
|
|
||||||
|
## Context Management
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# List all available contexts
|
||||||
|
kubectl config get-contexts
|
||||||
|
|
||||||
|
# Switch between clusters
|
||||||
|
kubectl config use-context fastpass-admin
|
||||||
|
kubectl config use-context hub-admin
|
||||||
|
kubectl config use-context internal-admin
|
||||||
|
|
||||||
|
# Check current context
|
||||||
|
kubectl config current-context
|
||||||
|
|
||||||
|
# Test connectivity
|
||||||
|
kubectl cluster-info
|
||||||
|
kubectl get nodes
|
||||||
|
```
|
||||||
|
|
||||||
|
## Integration with Existing Roles
|
||||||
|
|
||||||
|
### Before (Monolithic)
|
||||||
|
```yaml
|
||||||
|
# fastpass-first-control-plane/tasks/main.yml
|
||||||
|
- name: 50+ lines of kubeconfig logic
|
||||||
|
# Lots of repetitive code
|
||||||
|
```
|
||||||
|
|
||||||
|
### After (Modular)
|
||||||
|
```yaml
|
||||||
|
# fastpass-first-control-plane/tasks/main.yml
|
||||||
|
- name: Setup kubeconfig for FastPass cluster
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "{{ cluster_name }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Adding New Clusters
|
||||||
|
|
||||||
|
To add a new cluster (e.g., "edge-cluster"):
|
||||||
|
|
||||||
|
1. **Add to inventory:**
|
||||||
|
```yaml
|
||||||
|
edge_cluster:
|
||||||
|
hosts:
|
||||||
|
edge-node-01:
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Use the script:**
|
||||||
|
```bash
|
||||||
|
./scripts/setup-kubeconfig.sh edge edge_cluster[0]
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Or add to playbook:**
|
||||||
|
```yaml
|
||||||
|
- name: Setup kubeconfig for Edge cluster
|
||||||
|
hosts: edge_cluster[0]
|
||||||
|
roles:
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "edge"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Customization
|
||||||
|
|
||||||
|
### Different Kubeconfig Paths
|
||||||
|
```yaml
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "openshift-cluster"
|
||||||
|
kubeconfig_source_path: "/etc/kubernetes/static-pod-resources/kube-apiserver-certs/secrets/node-kubeconfigs/localhost.kubeconfig"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Context Names
|
||||||
|
```yaml
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "prod"
|
||||||
|
context_suffix: "system:admin" # Results in "prod-system:admin"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
1. **Permission Denied**
|
||||||
|
```bash
|
||||||
|
# Fix ownership
|
||||||
|
sudo chown -R $USER:$USER ~/.kube/
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Context Not Found**
|
||||||
|
```bash
|
||||||
|
# List available contexts
|
||||||
|
kubectl config get-contexts
|
||||||
|
|
||||||
|
# Check if cluster was added
|
||||||
|
kubectl config view
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Backup Recovery**
|
||||||
|
```bash
|
||||||
|
# Restore from backup
|
||||||
|
cp ~/.kube/config.backup.1697123456 ~/.kube/config
|
||||||
|
```
|
||||||
|
|
||||||
|
### Debug Mode
|
||||||
|
```bash
|
||||||
|
# Run with verbose output
|
||||||
|
ansible-playbook -vvv playbooks/examples/multi-cluster-kubeconfig.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Benefits for Your Homelab
|
||||||
|
|
||||||
|
1. **Consistency**: Same process for all clusters
|
||||||
|
2. **Maintainability**: Single role to update/fix
|
||||||
|
3. **Scalability**: Easy to add new clusters
|
||||||
|
4. **Safety**: Automatic backups and safe merging
|
||||||
|
5. **Flexibility**: Works with different Kubernetes distributions
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
1. **Test the modular approach** with your FastPass cluster
|
||||||
|
2. **Extend to Hub and Internal clusters** using the same pattern
|
||||||
|
3. **Create cluster-specific variables** in group_vars if needed
|
||||||
|
4. **Add monitoring/validation** tasks to verify kubeconfig health
|
||||||
|
|
||||||
|
This modular approach makes your homelab's multi-cluster management much more maintainable and repeatable!
|
||||||
@@ -15,3 +15,6 @@ base_domain: "local.mk-labs.cloud"
|
|||||||
|
|
||||||
# Terraform variables
|
# Terraform variables
|
||||||
terraform_server: "infra01"
|
terraform_server: "infra01"
|
||||||
|
|
||||||
|
# Traefik variables
|
||||||
|
traefik_server: "lightning-lane"
|
||||||
@@ -8,12 +8,12 @@ pod_network_cidr: "10.244.0.0/16"
|
|||||||
service_cidr: "10.96.0.0/12"
|
service_cidr: "10.96.0.0/12"
|
||||||
|
|
||||||
# Control Plane Configuration
|
# Control Plane Configuration
|
||||||
control_plane_endpoint: "fastpass.local.mk-labs.cloud"
|
control_plane_endpoint: "{{ cluster_name}}.{{ base_domain}}"
|
||||||
control_plane_port: "6443"
|
control_plane_port: "6443"
|
||||||
|
|
||||||
# CNI Configuration
|
# CNI Configuration
|
||||||
cni_plugin: "calico"
|
cni_plugin: "calico"
|
||||||
calico_version: "v3.28.0"
|
calico_version: "v3.30.3"
|
||||||
|
|
||||||
# Node Labels and Taints
|
# Node Labels and Taints
|
||||||
node_labels:
|
node_labels:
|
||||||
|
|||||||
59
ansible/host_vars/arcade/vars
Normal file
59
ansible/host_vars/arcade/vars
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
# file: host_vars/vm_template/vars
|
||||||
|
# Ansible vars template for hosts created via cloning.
|
||||||
|
|
||||||
|
# Supported hypervisors:
|
||||||
|
# - Proxmox
|
||||||
|
|
||||||
|
platform: "proxmox"
|
||||||
|
|
||||||
|
# This is the Proxmox node where all the VM templates are stored. (Templates are not global.)
|
||||||
|
|
||||||
|
proxmox_clone_node: "fantasyland"
|
||||||
|
|
||||||
|
# Templates are named in the following format (all lower case): <OS Distribution>-<OS Version>-<VM Size>
|
||||||
|
# Current OS offerings are:
|
||||||
|
# - Ubuntu
|
||||||
|
# - 24.04
|
||||||
|
# - Fedora
|
||||||
|
# - 42
|
||||||
|
|
||||||
|
vm_os_distribution: "ubuntu"
|
||||||
|
vm_os_version: "24.04"
|
||||||
|
|
||||||
|
# Current VM sizes are:
|
||||||
|
# - Small: 2 cores, 2GB memory, 8 GiB virtual disk
|
||||||
|
# - Medium: 2 cores, 4GB memory, 16 GiB virtual disk
|
||||||
|
# - Large: 4 cores, 4GB memory, 32 GiB virtual disk
|
||||||
|
# - Large Plus: 4 cores, 4GB memory, 48 GiB virtual disk
|
||||||
|
# - Xlarge: 4 cores, 8GB memory, 64 GiB virtual disk
|
||||||
|
# - Xlarge Plus: 4 cores, 8GB memory, 128 GiB virtual disk
|
||||||
|
|
||||||
|
vm_size: "large"
|
||||||
|
|
||||||
|
# Proxmox storage target.
|
||||||
|
|
||||||
|
vm_storage: "liberty-tree"
|
||||||
|
|
||||||
|
# Proxmox does not yet do dynamic load balancing, the host target sets the target for HA groups
|
||||||
|
# and backup groups. (ha_group will be factored out in the next functionality update.)
|
||||||
|
|
||||||
|
ha_group: "pve03"
|
||||||
|
proxmox_host_target: "pve03"
|
||||||
|
|
||||||
|
# Currently, only single NIC VMs using IPv4 are supported via cloning. The IP address also
|
||||||
|
# sets the Proxmox VMID. The VMID is a combination of the 3rd and 4th octet of the IPv4 address.
|
||||||
|
|
||||||
|
ip_address: 10.1.71.111
|
||||||
|
# vm_mac_address: 'BC:24:11:11:BC:58'
|
||||||
|
|
||||||
|
# Software
|
||||||
|
# Future enhancement will allow specification of additional software to automatically deploy to
|
||||||
|
# the VM after creation.
|
||||||
|
|
||||||
|
#terraform_version: "1.11.3"
|
||||||
|
|
||||||
|
# ---
|
||||||
|
|
||||||
|
vm_clone_source: "{{ vm_os_distribution }}-{{ vm_os_version }}-{{ vm_size }}"
|
||||||
|
hostname: "{{ inventory_hostname }}.{{ base_domain }}" # Change variable to fqdn
|
||||||
33
ansible/host_vars/lightning_lane/vars
Normal file
33
ansible/host_vars/lightning_lane/vars
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
# file: host_vars/lightning_lane/vars
|
||||||
|
# Traefik Load Balancer Server
|
||||||
|
|
||||||
|
# Supported hypervisors:
|
||||||
|
# - Proxmox
|
||||||
|
|
||||||
|
platform: "proxmox"
|
||||||
|
|
||||||
|
# This is the Proxmox node where all the VM templates are stored. (Templates are not global.)
|
||||||
|
proxmox_clone_node: "fantasyland"
|
||||||
|
|
||||||
|
# VM Configuration
|
||||||
|
vm_os_distribution: "ubuntu"
|
||||||
|
vm_os_version: "24.04"
|
||||||
|
vm_size: "medium"
|
||||||
|
vm_storage: "general"
|
||||||
|
|
||||||
|
# Proxmox HA Configuration
|
||||||
|
ha_group: "pve02"
|
||||||
|
proxmox_host_target: "pve02"
|
||||||
|
|
||||||
|
# Network Configuration
|
||||||
|
# IP address for the Traefik load balancer
|
||||||
|
ip_address: 10.1.71.80
|
||||||
|
vm_mac_address: 'BC:24:11:50:00:80'
|
||||||
|
|
||||||
|
# Software Configuration
|
||||||
|
# Traefik will be installed and configured on this host
|
||||||
|
|
||||||
|
# VM Template Configuration
|
||||||
|
vm_clone_source: "{{ vm_os_distribution }}-{{ vm_os_version }}-{{ vm_size }}"
|
||||||
|
hostname: "{{ inventory_hostname }}.{{ base_domain }}"
|
||||||
@@ -37,6 +37,11 @@ prometheus_nodes:
|
|||||||
# hosts:
|
# hosts:
|
||||||
# cinderella-castle:
|
# cinderella-castle:
|
||||||
|
|
||||||
|
papermc_server:
|
||||||
|
# ansible-galaxy role install engonzal.papermc
|
||||||
|
hosts:
|
||||||
|
arcade:
|
||||||
|
|
||||||
semaphore_server:
|
semaphore_server:
|
||||||
hosts:
|
hosts:
|
||||||
imagineering:
|
imagineering:
|
||||||
@@ -45,6 +50,10 @@ n8n_server:
|
|||||||
hosts:
|
hosts:
|
||||||
tiki-room:
|
tiki-room:
|
||||||
|
|
||||||
|
traefik_server:
|
||||||
|
hosts:
|
||||||
|
lightning_lane:
|
||||||
|
|
||||||
# dhcp_server:
|
# dhcp_server:
|
||||||
# hosts:
|
# hosts:
|
||||||
# matchbox:
|
# matchbox:
|
||||||
|
|||||||
@@ -1,17 +1,13 @@
|
|||||||
---
|
---
|
||||||
- name: Add entry to DNS
|
# Replacement for add_technitium_dns_entry.yml
|
||||||
|
# This playbook uses the modular task file approach
|
||||||
|
|
||||||
|
- name: Add DNS entry using Technitium DNS
|
||||||
hosts: all
|
hosts: all
|
||||||
gather_facts: false
|
gather_facts: false
|
||||||
|
|
||||||
tasks:
|
tasks:
|
||||||
- name: Create DNS entry for {{ inventory_hostname }}
|
- name: Include Technitium DNS entry task
|
||||||
delegate_to: "{{ groups['ipaserver'][0] }}"
|
ansible.builtin.include_tasks: tasks/add_technitium_dns_entry.yml
|
||||||
freeipa.ansible_freeipa.ipadnsrecord:
|
vars:
|
||||||
ipaapi_context: "server"
|
host_name: "{{ inventory_hostname }}"
|
||||||
ipaadmin_password: "{{ vault_freeipa_password }}"
|
|
||||||
name: "{{ inventory_hostname }}"
|
|
||||||
zone_name: "{{ base_domain }}"
|
|
||||||
record_type: "A"
|
|
||||||
record_value: "{{ ip_address }}"
|
|
||||||
record_ttl: 60
|
|
||||||
# create_reverse: yes
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
when: vm_os_distribution == "ubuntu"
|
when: vm_os_distribution == "ubuntu"
|
||||||
|
|
||||||
- name: DNS Playbook
|
- name: DNS Playbook
|
||||||
ansible.builtin.import_playbook: add_technitium_dns_entry.yml
|
ansible.builtin.import_playbook: add_dns_entry.yml
|
||||||
|
|
||||||
- name: DHCP Playbook
|
- name: DHCP Playbook
|
||||||
ansible.builtin.import_playbook: add_dhcp_reservation.yml
|
ansible.builtin.import_playbook: add_dhcp_reservation.yml
|
||||||
|
|||||||
@@ -6,19 +6,21 @@
|
|||||||
# roles:
|
# roles:
|
||||||
# - role: kubernetes-prerequisites
|
# - role: kubernetes-prerequisites
|
||||||
|
|
||||||
- name: Step 2 - Deploy First Control Plane Node
|
# - name: Step 2 - Deploy First Control Plane Node
|
||||||
hosts: fastpass_control_plane[0]
|
# hosts: fastpass_control_plane[0]
|
||||||
become: true
|
|
||||||
gather_facts: true # false
|
|
||||||
roles:
|
|
||||||
- role: fastpass-first-control-plane
|
|
||||||
|
|
||||||
# - name: Step 3 - Deploy Additional Control Plane Nodes
|
|
||||||
# hosts: fastpass_control_plane[1:]
|
|
||||||
# become: true
|
# become: true
|
||||||
# gather_facts: false
|
# gather_facts: false
|
||||||
# roles:
|
# roles:
|
||||||
# - role: fastpass-additional-control-plane
|
# - role: fastpass-first-control-plane
|
||||||
|
|
||||||
|
- name: Step 3 - Deploy Additional Control Plane Nodes
|
||||||
|
hosts: fastpass_control_plane[1:]
|
||||||
|
become: true
|
||||||
|
gather_facts: true # false
|
||||||
|
roles:
|
||||||
|
- role: fastpass-additional-control-plane
|
||||||
|
vars:
|
||||||
|
cluster_name: "fastpass"
|
||||||
|
|
||||||
# - name: Step 4 - Deploy Worker Nodes
|
# - name: Step 4 - Deploy Worker Nodes
|
||||||
# hosts: fastpass_workers
|
# hosts: fastpass_workers
|
||||||
@@ -26,18 +28,3 @@
|
|||||||
# gather_facts: false
|
# gather_facts: false
|
||||||
# roles:
|
# roles:
|
||||||
# - role: fastpass-workers
|
# - role: fastpass-workers
|
||||||
|
|
||||||
# - name: Final Cluster Validation
|
|
||||||
# hosts: fastpass_control_plane[0]
|
|
||||||
# become: false
|
|
||||||
# gather_facts: false
|
|
||||||
# environment:
|
|
||||||
# KUBECONFIG: "{{ kubeconfig_path }}"
|
|
||||||
# tasks:
|
|
||||||
# - name: Display cluster status
|
|
||||||
# ansible.builtin.command: kubectl get nodes
|
|
||||||
# delegate_to: localhost
|
|
||||||
|
|
||||||
# - name: Display all pods
|
|
||||||
# ansible.builtin.command: kubectl get pods -A
|
|
||||||
# delegate_to: localhost
|
|
||||||
|
|||||||
28
ansible/playbooks/deploy_minecraft.yml
Normal file
28
ansible/playbooks/deploy_minecraft.yml
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
- name: 1. Deploy Paper Minecraft server
|
||||||
|
hosts: papermc_server
|
||||||
|
vars:
|
||||||
|
papermc_mem: 2G
|
||||||
|
papermc_server_port: 25565
|
||||||
|
papermc_motd: "MK-Labs Minecraft Server"
|
||||||
|
papermc_broadcast_console_to_ops: false
|
||||||
|
papermc_version: 1.21.8
|
||||||
|
papermc_dir_main: /app/minecraft
|
||||||
|
papermc_dir_data: /app/minecraft/data
|
||||||
|
papermc_dir_logs: /app/minecraft/logs
|
||||||
|
papermc_dir_plugins: /app/minecraft/plugins
|
||||||
|
papermc_dir_worlds: /app/minecraft/worlds
|
||||||
|
papermc_dir_worlds_nether: /app/minecraft/worlds/nether
|
||||||
|
papermc_dir_worlds_the_end: /app/minecraft/worlds/the_end
|
||||||
|
papermc_dir_worlds_world: /app/minecraft/worlds/world
|
||||||
|
papermc_jar_url: https://papermc.io/api/v2/projects/paper/versions/{{ papermc_version }}/builds/latest/downloads/paper-{{ papermc_version }}-{{ papermc_build }}.jar
|
||||||
|
papermc_jar_path: /opt/papermc/paper-{{ papermc_version }}-{{ papermc_build }}.jar
|
||||||
|
papermc_jar_checksum_type: sha256
|
||||||
|
papermc_jar_checksum_path: /opt/papermc/paper-{{ papermc_version }}-{{ papermc_build }}.jar.sha256
|
||||||
|
papermc_whitelist:
|
||||||
|
- ryansrailroad
|
||||||
|
papermc_white_list: "true"
|
||||||
|
papermc_enforce_whitelist: "true"
|
||||||
|
roles:
|
||||||
|
- role: engonzal.papermc
|
||||||
|
become: yes
|
||||||
41
ansible/playbooks/examples/multi-cluster-kubeconfig.yml
Normal file
41
ansible/playbooks/examples/multi-cluster-kubeconfig.yml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
---
|
||||||
|
# Example playbook showing how to use the modular kubeconfig management
|
||||||
|
# across multiple clusters in your homelab
|
||||||
|
|
||||||
|
- name: Setup kubeconfig for FastPass cluster
|
||||||
|
hosts: fastpass_control_plane[0]
|
||||||
|
gather_facts: true
|
||||||
|
roles:
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "fastpass"
|
||||||
|
|
||||||
|
- name: Setup kubeconfig for Hub cluster
|
||||||
|
hosts: hub_cluster
|
||||||
|
gather_facts: true
|
||||||
|
roles:
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "hub"
|
||||||
|
|
||||||
|
- name: Setup kubeconfig for Internal cluster
|
||||||
|
hosts: internal_cluster[0]
|
||||||
|
gather_facts: true
|
||||||
|
roles:
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "internal"
|
||||||
|
|
||||||
|
# Alternative approach using the generic cluster-kubeconfig role
|
||||||
|
- name: Setup kubeconfig for any cluster
|
||||||
|
hosts: "{{ target_cluster_hosts }}"
|
||||||
|
gather_facts: true
|
||||||
|
roles:
|
||||||
|
- role: cluster-kubeconfig
|
||||||
|
vars:
|
||||||
|
cluster_name: "{{ target_cluster_name }}"
|
||||||
|
|
||||||
|
# Usage examples:
|
||||||
|
# ansible-playbook -i inventory.yml examples/multi-cluster-kubeconfig.yml
|
||||||
|
# ansible-playbook -i inventory.yml examples/multi-cluster-kubeconfig.yml --limit fastpass_control_plane[0]
|
||||||
|
# ansible-playbook -i inventory.yml examples/multi-cluster-kubeconfig.yml -e target_cluster_hosts=hub_cluster -e target_cluster_name=hub
|
||||||
60
ansible/playbooks/examples/setup-fastpass-network.yml
Normal file
60
ansible/playbooks/examples/setup-fastpass-network.yml
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
---
|
||||||
|
# Example: Setup network infrastructure for FastPass cluster
|
||||||
|
# This demonstrates the modular approach for DNS and load balancer setup
|
||||||
|
|
||||||
|
- name: Setup FastPass Cluster Network Infrastructure
|
||||||
|
hosts: fastpass_control_plane[0]
|
||||||
|
gather_facts: true
|
||||||
|
vars:
|
||||||
|
cluster_name: "fastpass"
|
||||||
|
cluster_endpoint: "{{ control_plane_endpoint }}"
|
||||||
|
cluster_vip: "{{ ansible_default_ipv4.address }}"
|
||||||
|
control_plane_nodes: "{{ groups['fastpass_control_plane'] }}"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Display cluster configuration
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: |
|
||||||
|
Setting up network for FastPass cluster:
|
||||||
|
- Cluster Name: {{ cluster_name }}
|
||||||
|
- Endpoint: {{ cluster_endpoint }}
|
||||||
|
- VIP: {{ cluster_vip }}
|
||||||
|
- Control Plane Nodes: {{ control_plane_nodes | join(', ') }}
|
||||||
|
|
||||||
|
- name: Setup cluster network infrastructure
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: cluster-network-setup
|
||||||
|
vars:
|
||||||
|
cluster_name: "{{ cluster_name }}"
|
||||||
|
cluster_endpoint: "{{ cluster_endpoint }}"
|
||||||
|
cluster_vip: "{{ cluster_vip }}"
|
||||||
|
control_plane_nodes: "{{ control_plane_nodes }}"
|
||||||
|
|
||||||
|
# Alternative approach using task file directly
|
||||||
|
- name: Alternative - Use Technitium DNS task directly
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: false
|
||||||
|
vars:
|
||||||
|
cluster_endpoint: "{{ hostvars[groups['fastpass_control_plane'][0]]['control_plane_endpoint'] }}"
|
||||||
|
cluster_vip: "{{ hostvars[groups['fastpass_control_plane'][0]]['ansible_default_ipv4']['address'] }}"
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
- name: Create DNS entry using task file
|
||||||
|
ansible.builtin.include_tasks: ../tasks/add_technitium_dns_entry.yml
|
||||||
|
vars:
|
||||||
|
dns_record_name: "{{ cluster_endpoint.split('.')[0] }}"
|
||||||
|
dns_zone: "{{ base_domain }}"
|
||||||
|
dns_ip_address: "{{ cluster_vip }}"
|
||||||
|
dns_record_type: "A"
|
||||||
|
dns_ttl: 360
|
||||||
|
dns_create_ptr: true
|
||||||
|
dns_debug: true
|
||||||
|
when: use_task_approach | default(false)
|
||||||
|
|
||||||
|
# Usage examples:
|
||||||
|
#
|
||||||
|
# Use modular approach (recommended):
|
||||||
|
# ansible-playbook -i inventory.yml playbooks/examples/setup-fastpass-network.yml
|
||||||
|
#
|
||||||
|
# Use task file approach:
|
||||||
|
# ansible-playbook -i inventory.yml playbooks/examples/setup-fastpass-network.yml -e use_task_approach=true
|
||||||
12
ansible/playbooks/roles/cluster-kubeconfig/tasks/main.yml
Normal file
12
ansible/playbooks/roles/cluster-kubeconfig/tasks/main.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
# role: cluster-kubeconfig
|
||||||
|
# description: Generic role for any Kubernetes cluster kubeconfig management
|
||||||
|
# author: mk-labs
|
||||||
|
# version: 1.0.0
|
||||||
|
|
||||||
|
- name: Setup kubeconfig for {{ cluster_name }} cluster
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "{{ cluster_name }}"
|
||||||
|
kubeconfig_source_path: "{{ kubeconfig_source_path | default('/etc/kubernetes/admin.conf') }}"
|
||||||
48
ansible/playbooks/roles/cluster-network-setup/tasks/main.yml
Normal file
48
ansible/playbooks/roles/cluster-network-setup/tasks/main.yml
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
# role: cluster-network-setup
|
||||||
|
# description: Combined DNS and Load Balancer setup for Kubernetes clusters
|
||||||
|
# author: mk-labs
|
||||||
|
# version: 1.0.0
|
||||||
|
|
||||||
|
- name: Setup DNS entry for cluster
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: dns-manager
|
||||||
|
vars:
|
||||||
|
cluster_endpoint: "{{ cluster_endpoint }}"
|
||||||
|
cluster_vip: "{{ cluster_vip }}"
|
||||||
|
|
||||||
|
- name: Setup Traefik load balancer for cluster
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: traefik-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "{{ cluster_name }}"
|
||||||
|
cluster_endpoint: "{{ cluster_endpoint }}"
|
||||||
|
control_plane_nodes: "{{ control_plane_nodes }}"
|
||||||
|
when: traefik_enabled | default(true)
|
||||||
|
|
||||||
|
- name: Wait for DNS propagation
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
timeout: 30
|
||||||
|
delegate_to: localhost
|
||||||
|
|
||||||
|
- name: Test cluster endpoint connectivity
|
||||||
|
ansible.builtin.wait_for:
|
||||||
|
host: "{{ cluster_endpoint }}"
|
||||||
|
port: "{{ cluster_api_port | default(6443) }}"
|
||||||
|
timeout: 60
|
||||||
|
delegate_to: localhost
|
||||||
|
register: connectivity_test
|
||||||
|
failed_when: false
|
||||||
|
|
||||||
|
- name: Display network setup results
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: |
|
||||||
|
🌐 Network Setup Complete for {{ cluster_name }}:
|
||||||
|
|
||||||
|
DNS Entry: {{ cluster_endpoint }} → {{ cluster_vip }}
|
||||||
|
Load Balancer: {{ 'Configured' if traefik_enabled | default(true) else 'Skipped' }}
|
||||||
|
Connectivity: {{ 'Success' if connectivity_test.failed == false else 'Failed - Check firewall/network' }}
|
||||||
|
|
||||||
|
Next steps:
|
||||||
|
1. Verify: kubectl --kubeconfig ~/.kube/config-{{ cluster_name }} cluster-info
|
||||||
|
2. Switch context: kubectl config use-context {{ cluster_name }}-admin
|
||||||
18
ansible/playbooks/roles/dns-manager/defaults/main.yml
Normal file
18
ansible/playbooks/roles/dns-manager/defaults/main.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
# Default variables for dns-manager role
|
||||||
|
|
||||||
|
# DNS Configuration
|
||||||
|
dns_management_enabled: true
|
||||||
|
use_hosts_file_fallback: false
|
||||||
|
dns_ttl: 360
|
||||||
|
dns_propagation_wait: 2
|
||||||
|
create_ptr_record: true
|
||||||
|
|
||||||
|
# Cluster Configuration (to be provided by calling role)
|
||||||
|
# cluster_endpoint: "fastpass.local.mk-labs.cloud"
|
||||||
|
# cluster_vip: "10.1.71.53"
|
||||||
|
|
||||||
|
# DNS Server Configuration (from group_vars)
|
||||||
|
# dns_server: "monorail"
|
||||||
|
# base_domain: "local.mk-labs.cloud"
|
||||||
|
# vault_technitium_api_key: "{{ vault_technitium_api_key }}"
|
||||||
17
ansible/playbooks/roles/dns-manager/tasks/main.yml
Normal file
17
ansible/playbooks/roles/dns-manager/tasks/main.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
---
|
||||||
|
# role: dns-manager
|
||||||
|
# description: Reusable role for managing DNS entries across clusters using Technitium DNS
|
||||||
|
# author: mk-labs
|
||||||
|
# version: 1.0.0
|
||||||
|
|
||||||
|
- name: Create DNS entry using Technitium DNS task
|
||||||
|
ansible.builtin.include_tasks: "{{ playbook_dir }}/tasks/add_technitium_dns_entry.yml"
|
||||||
|
|
||||||
|
- name: Wait for DNS propagation
|
||||||
|
ansible.builtin.pause:
|
||||||
|
seconds: "{{ dns_propagation_wait | default(10) }}"
|
||||||
|
when: dns_management_enabled | default(true)
|
||||||
|
|
||||||
|
- name: Look up A (IPv4) records for example.org
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "{{ query('community.dns.lookup', 'fastpass') }}"
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
Role Name
|
||||||
|
=========
|
||||||
|
|
||||||
|
A brief description of the role goes here.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
|
||||||
|
|
||||||
|
Role Variables
|
||||||
|
--------------
|
||||||
|
|
||||||
|
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
|
||||||
|
|
||||||
|
Example Playbook
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
|
||||||
|
|
||||||
|
- hosts: servers
|
||||||
|
roles:
|
||||||
|
- { role: username.rolename, x: 42 }
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
BSD
|
||||||
|
|
||||||
|
Author Information
|
||||||
|
------------------
|
||||||
|
|
||||||
|
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
---
|
||||||
|
# FastPass Additional Control Plane Role Defaults
|
||||||
|
|
||||||
|
# Kubernetes services for control plane
|
||||||
|
kubernetes_services_control_plane:
|
||||||
|
- kubernetes_API
|
||||||
|
- etcd
|
||||||
|
- kubelet
|
||||||
|
- kube-scheduler
|
||||||
|
- kube-controller-manager
|
||||||
|
|
||||||
|
# Join token configuration
|
||||||
|
join_token_ttl: "24h"
|
||||||
|
certificate_key_ttl: "2h"
|
||||||
|
|
||||||
|
# Default cluster configuration
|
||||||
|
pod_network_cidr: "10.244.0.0/16"
|
||||||
|
service_cidr: "10.96.0.0/12"
|
||||||
|
|
||||||
|
# Kubelet configuration
|
||||||
|
kubelet_cgroup_driver: "systemd"
|
||||||
|
container_runtime_endpoint: "unix:///run/containerd/containerd.sock"
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
# handlers file for fastpass-additional-control-plane
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
author: Ryan Blundon
|
||||||
|
description: FastPass Additional Control Plane - Deploy additional control plane nodes to existing FastPass Kubernetes cluster
|
||||||
|
company: Homelab
|
||||||
|
|
||||||
|
license: MIT
|
||||||
|
|
||||||
|
min_ansible_version: "2.9"
|
||||||
|
|
||||||
|
platforms:
|
||||||
|
- name: Ubuntu
|
||||||
|
versions:
|
||||||
|
- focal
|
||||||
|
- jammy
|
||||||
|
- name: Debian
|
||||||
|
versions:
|
||||||
|
- bullseye
|
||||||
|
- bookworm
|
||||||
|
|
||||||
|
galaxy_tags:
|
||||||
|
- kubernetes
|
||||||
|
- k8s
|
||||||
|
- controlplane
|
||||||
|
- cluster
|
||||||
|
- fastpass
|
||||||
|
- kubeadm
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- role: dns-manager
|
||||||
|
when: cluster_name is defined
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
when: cluster_name is defined
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
# role: fastpass-additional-control-plane
|
||||||
|
# description: FastPass Additional Control Plane - Deploy additional control plane nodes to existing FastPass Kubernetes cluster
|
||||||
|
# author: Ryan Blundon
|
||||||
|
# version: 1.0.0
|
||||||
|
# date: 2025-10-05
|
||||||
|
|
||||||
|
# This role joins additional nodes to an existing Kubernetes cluster as control plane nodes
|
||||||
|
# It follows the same patterns as fastpass-first-control-plane but uses kubeadm join instead of kubeadm init
|
||||||
|
|
||||||
|
- name: Display role information
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Starting FastPass Additional Control Plane deployment for {{ inventory_hostname }}"
|
||||||
|
|
||||||
|
- name: Setup DNS record for cluster
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: dns-manager
|
||||||
|
vars:
|
||||||
|
host_name: "{{ cluster_name }}"
|
||||||
|
|
||||||
|
- name: Open services for control plane
|
||||||
|
become: true
|
||||||
|
when: ansible_os_family == "Debian"
|
||||||
|
block:
|
||||||
|
- name: Open firewall ports for control plane
|
||||||
|
community.general.ufw:
|
||||||
|
rule: allow
|
||||||
|
name: "{{ item }}"
|
||||||
|
loop: "{{ kubernetes_services_control_plane }}"
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
localhost
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
remote_user: root
|
||||||
|
roles:
|
||||||
|
- fastpass-additional-control-plane
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
---
|
||||||
|
# vars file for fastpass-additional-control-plane
|
||||||
@@ -1,11 +1,16 @@
|
|||||||
---
|
---
|
||||||
# role: fastpass-first-control-plane
|
# role: fastpass-first-control-plane
|
||||||
# description: FastPass First Control Plane
|
# description: FastPass First Control Plane
|
||||||
# author: mk-labs
|
# author: Ryan Blundon
|
||||||
# version: 1.0.0
|
# version: 1.0.0
|
||||||
# date: 2025-09-27
|
# date: 2025-09-27
|
||||||
|
|
||||||
# Open sevices for control plane
|
- name: Setup DNS record for cluster
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: dns-manager
|
||||||
|
vars:
|
||||||
|
host_name: "{{ cluster_name }}"
|
||||||
|
|
||||||
- name: Open services for control plane
|
- name: Open services for control plane
|
||||||
become: true
|
become: true
|
||||||
when: ansible_os_family == "Debian"
|
when: ansible_os_family == "Debian"
|
||||||
@@ -14,8 +19,7 @@
|
|||||||
community.general.ufw:
|
community.general.ufw:
|
||||||
rule: allow
|
rule: allow
|
||||||
name: "{{ item }}"
|
name: "{{ item }}"
|
||||||
loop:
|
loop: "{{ kubernetes_services_control_plane }}"
|
||||||
"{{ kubernetes_services_control_plane }}"
|
|
||||||
|
|
||||||
- name: Create initial kubelet config file
|
- name: Create initial kubelet config file
|
||||||
become: true
|
become: true
|
||||||
@@ -23,20 +27,27 @@
|
|||||||
dest: /var/lib/kubelet/config.yaml
|
dest: /var/lib/kubelet/config.yaml
|
||||||
owner: root
|
owner: root
|
||||||
group: root
|
group: root
|
||||||
mode: '0644'
|
mode: "0644"
|
||||||
content: |
|
content: |
|
||||||
apiVersion: kubelet.config.k8s.io/v1beta1
|
apiVersion: kubelet.config.k8s.io/v1beta1
|
||||||
kind: KubeletConfiguration
|
kind: KubeletConfiguration
|
||||||
cgroupDriver: systemd
|
cgroupDriver: systemd
|
||||||
containerRuntimeEndpoint: unix:///run/containerd/containerd.sock
|
containerRuntimeEndpoint: unix:///run/containerd/containerd.sock
|
||||||
|
|
||||||
# - name: Initialize Kubernetes cluster
|
- name: Initialize Kubernetes cluster
|
||||||
# become: true
|
become: true
|
||||||
# ansible.builtin.command: kubeadm init --ignore-preflight-errors=NumCPU,Mem --control-plane-endpoint=fastpass # {{ cluster_name }}
|
ansible.builtin.command:
|
||||||
# args:
|
argv:
|
||||||
# creates: /etc/kubernetes/admin.conf
|
- kubeadm
|
||||||
# register: kubeadm_init
|
- init
|
||||||
# changed_when: kubeadm_init.rc == 0
|
- --apiserver-advertise-address={{ ip_address }}
|
||||||
|
- --control-plane-endpoint={{ cluster_name }}
|
||||||
|
- --pod-network-cidr={{ pod_network_cidr }}
|
||||||
|
- --service-cidr={{ service_cidr }}
|
||||||
|
args:
|
||||||
|
creates: /etc/kubernetes/admin.conf
|
||||||
|
register: kubeadm_init
|
||||||
|
changed_when: kubeadm_init.rc == 0
|
||||||
|
|
||||||
- name: Ensure kubelet is enabled and started
|
- name: Ensure kubelet is enabled and started
|
||||||
become: true
|
become: true
|
||||||
@@ -44,23 +55,49 @@
|
|||||||
name: kubelet
|
name: kubelet
|
||||||
enabled: true
|
enabled: true
|
||||||
state: started
|
state: started
|
||||||
|
|
||||||
- name: Debug ansible_env.HOME
|
- name: Setup kubeconfig for FastPass cluster
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: kubeconfig-manager
|
||||||
|
|
||||||
|
# - name: Download tigera-operator manifest
|
||||||
|
# delegate_to: localhost
|
||||||
|
# ansible.builtin.get_url:
|
||||||
|
# url: https://raw.githubusercontent.com/projectcalico/calico/{{ calico_version }}/manifests/tigera-operator.yaml
|
||||||
|
# dest: /tmp/tigera-operator.yaml
|
||||||
|
# mode: "0644"
|
||||||
|
|
||||||
|
# - name: Install tigera-operator from downloaded file
|
||||||
|
# delegate_to: localhost
|
||||||
|
# kubernetes.core.k8s:
|
||||||
|
# kubeconfig: "{{ local_home }}/.kube/config"
|
||||||
|
# state: present
|
||||||
|
# src: /tmp/tigera-operator.yaml
|
||||||
|
|
||||||
|
# - name: Download Calico CRDs
|
||||||
|
# delegate_to: localhost
|
||||||
|
# ansible.builtin.get_url:
|
||||||
|
# url: https://raw.githubusercontent.com/projectcalico/calico/{{ calico_version }}/manifests/custom-resources.yaml
|
||||||
|
# dest: /tmp/custom-resources.yaml
|
||||||
|
# mode: "0644"
|
||||||
|
|
||||||
|
# - name: Install Calico CRDs from downloaded file
|
||||||
|
# delegate_to: localhost
|
||||||
|
# kubernetes.core.k8s:
|
||||||
|
# kubeconfig: "{{ local_home }}/.kube/config"
|
||||||
|
# state: present
|
||||||
|
# src: /tmp/custom-resources.yaml
|
||||||
|
|
||||||
|
- name: Download Flannel CNI
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
ansible.builtin.debug:
|
ansible.builtin.get_url:
|
||||||
var: ansible_env.HOME
|
url: https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
|
||||||
|
dest: /tmp/kube-flannel.yaml
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Install Flannel CNI from downloaded file
|
||||||
- name: Create .kube directory for user
|
|
||||||
delegate_to: localhost
|
delegate_to: localhost
|
||||||
ansible.builtin.file:
|
kubernetes.core.k8s:
|
||||||
path: "{{ ansible_env.HOME }}/.kube"
|
kubeconfig: "{{ local_home }}/.kube/config"
|
||||||
state: directory
|
state: present
|
||||||
mode: '0755'
|
src: /tmp/kube-flannel.yaml
|
||||||
|
|
||||||
- name: Copy admin.conf to user's .kube directory on controller
|
|
||||||
ansible.builtin.fetch:
|
|
||||||
src: /etc/kubernetes/admin.conf
|
|
||||||
dest: "{{ ansible_env.HOME }}/.kube/config-fastpass" # {{cluster_name}}"
|
|
||||||
mode: '0644'
|
|
||||||
|
|
||||||
|
|||||||
38
ansible/playbooks/roles/fastpass-worker-nodes/README.md
Normal file
38
ansible/playbooks/roles/fastpass-worker-nodes/README.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
Role Name
|
||||||
|
=========
|
||||||
|
|
||||||
|
A brief description of the role goes here.
|
||||||
|
|
||||||
|
Requirements
|
||||||
|
------------
|
||||||
|
|
||||||
|
Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required.
|
||||||
|
|
||||||
|
Role Variables
|
||||||
|
--------------
|
||||||
|
|
||||||
|
A description of the settable variables for this role should go here, including any variables that are in defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well.
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
------------
|
||||||
|
|
||||||
|
A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set for other roles, or variables that are used from other roles.
|
||||||
|
|
||||||
|
Example Playbook
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for users too:
|
||||||
|
|
||||||
|
- hosts: servers
|
||||||
|
roles:
|
||||||
|
- { role: username.rolename, x: 42 }
|
||||||
|
|
||||||
|
License
|
||||||
|
-------
|
||||||
|
|
||||||
|
BSD
|
||||||
|
|
||||||
|
Author Information
|
||||||
|
------------------
|
||||||
|
|
||||||
|
An optional section for the role authors to include contact information, or a website (HTML is not allowed).
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# defaults file for fastpass-worker-nodes
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# handlers file for fastpass-worker-nodes
|
||||||
35
ansible/playbooks/roles/fastpass-worker-nodes/meta/main.yml
Normal file
35
ansible/playbooks/roles/fastpass-worker-nodes/meta/main.yml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
galaxy_info:
|
||||||
|
author: your name
|
||||||
|
description: your role description
|
||||||
|
company: your company (optional)
|
||||||
|
|
||||||
|
# If the issue tracker for your role is not on github, uncomment the
|
||||||
|
# next line and provide a value
|
||||||
|
# issue_tracker_url: http://example.com/issue/tracker
|
||||||
|
|
||||||
|
# Choose a valid license ID from https://spdx.org - some suggested licenses:
|
||||||
|
# - BSD-3-Clause (default)
|
||||||
|
# - MIT
|
||||||
|
# - GPL-2.0-or-later
|
||||||
|
# - GPL-3.0-only
|
||||||
|
# - Apache-2.0
|
||||||
|
# - CC-BY-4.0
|
||||||
|
license: license (GPL-2.0-or-later, MIT, etc)
|
||||||
|
|
||||||
|
min_ansible_version: 2.1
|
||||||
|
|
||||||
|
# If this a Container Enabled role, provide the minimum Ansible Container version.
|
||||||
|
# min_ansible_container_version:
|
||||||
|
|
||||||
|
galaxy_tags: []
|
||||||
|
# List tags for your role here, one per line. A tag is a keyword that describes
|
||||||
|
# and categorizes the role. Users find roles by searching for tags. Be sure to
|
||||||
|
# remove the '[]' above, if you add tags to this list.
|
||||||
|
#
|
||||||
|
# NOTE: A tag is limited to a single word comprised of alphanumeric characters.
|
||||||
|
# Maximum 20 tags per role.
|
||||||
|
|
||||||
|
dependencies: []
|
||||||
|
# List your role dependencies here, one per line. Be sure to remove the '[]' above,
|
||||||
|
# if you add dependencies to this list.
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# tasks file for fastpass-worker-nodes
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
localhost
|
||||||
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
remote_user: root
|
||||||
|
roles:
|
||||||
|
- fastpass-worker-nodes
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#SPDX-License-Identifier: MIT-0
|
||||||
|
---
|
||||||
|
# vars file for fastpass-worker-nodes
|
||||||
86
ansible/playbooks/roles/kubeconfig-manager/README.md
Normal file
86
ansible/playbooks/roles/kubeconfig-manager/README.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
# Kubeconfig Manager Role
|
||||||
|
|
||||||
|
A reusable Ansible role for managing kubeconfig files across multiple Kubernetes clusters.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Fetches kubeconfig from remote Kubernetes nodes
|
||||||
|
- Merges multiple cluster configs into a single `~/.kube/config` file
|
||||||
|
- Creates backups before merging
|
||||||
|
- Provides unique cluster, context, and user names
|
||||||
|
- Works with any Kubernetes cluster (vanilla K8s, OpenShift, etc.)
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Ansible 2.9+
|
||||||
|
- Access to Kubernetes cluster admin.conf file
|
||||||
|
- Local kubectl installation (optional, for testing)
|
||||||
|
|
||||||
|
## Role Variables
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `cluster_name` | `kubernetes` | Name of the cluster (required) |
|
||||||
|
| `kubeconfig_source_path` | `/etc/kubernetes/admin.conf` | Path to kubeconfig on remote host |
|
||||||
|
| `context_suffix` | `admin` | Suffix for context name |
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
### In a playbook:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Setup kubeconfig for FastPass cluster
|
||||||
|
hosts: fastpass_control_plane[0]
|
||||||
|
roles:
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "fastpass"
|
||||||
|
|
||||||
|
- name: Setup kubeconfig for Hub cluster
|
||||||
|
hosts: hub_cluster
|
||||||
|
roles:
|
||||||
|
- role: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "hub"
|
||||||
|
kubeconfig_source_path: "/etc/kubernetes/admin.conf"
|
||||||
|
```
|
||||||
|
|
||||||
|
### As an included role:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Manage kubeconfig
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: kubeconfig-manager
|
||||||
|
vars:
|
||||||
|
cluster_name: "{{ my_cluster_name }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generated Structure
|
||||||
|
|
||||||
|
The role creates contexts with this naming pattern:
|
||||||
|
- **Cluster**: `{{ cluster_name }}`
|
||||||
|
- **Context**: `{{ cluster_name }}-admin`
|
||||||
|
- **User**: `{{ cluster_name }}-admin`
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
```
|
||||||
|
~/.kube/
|
||||||
|
├── config # Merged kubeconfig
|
||||||
|
├── config-fastpass # Individual cluster configs
|
||||||
|
├── config-hub
|
||||||
|
├── config-internal
|
||||||
|
└── config.backup.1234567890 # Timestamped backups
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dependencies
|
||||||
|
|
||||||
|
None
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT
|
||||||
|
|
||||||
|
## Author
|
||||||
|
|
||||||
|
mk-labs
|
||||||
11
ansible/playbooks/roles/kubeconfig-manager/defaults/main.yml
Normal file
11
ansible/playbooks/roles/kubeconfig-manager/defaults/main.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
# Default variables for kubeconfig-manager role
|
||||||
|
|
||||||
|
# Source path for the kubeconfig file on the remote host
|
||||||
|
kubeconfig_source_path: "/etc/kubernetes/admin.conf"
|
||||||
|
|
||||||
|
# Cluster name - should be provided by the calling playbook
|
||||||
|
cluster_name: "kubernetes"
|
||||||
|
|
||||||
|
# Context suffix for the cluster
|
||||||
|
context_suffix: "admin"
|
||||||
34
ansible/playbooks/roles/kubeconfig-manager/tasks/main.yml
Normal file
34
ansible/playbooks/roles/kubeconfig-manager/tasks/main.yml
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
---
|
||||||
|
# role: kubeconfig-manager
|
||||||
|
# description: Reusable role for managing kubeconfig files across multiple clusters
|
||||||
|
# author: mk-labs
|
||||||
|
# version: 1.0.0
|
||||||
|
|
||||||
|
- name: Get local user environment
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
local_home: "{{ lookup('env', 'HOME') }}"
|
||||||
|
local_user: "{{ lookup('env', 'USER') }}"
|
||||||
|
|
||||||
|
- name: Debug local environment
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: "Local user: {{ local_user }}, Home directory: {{ local_home }}"
|
||||||
|
|
||||||
|
- name: Create .kube directory
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ local_home }}/.kube"
|
||||||
|
state: directory
|
||||||
|
owner: "{{ local_user }}"
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Copy kubeconfig from remote host
|
||||||
|
ansible.builtin.fetch:
|
||||||
|
src: "{{ kubeconfig_source_path | default('/etc/kubernetes/admin.conf') }}"
|
||||||
|
dest: "{{ local_home }}/.kube/config-{{ cluster_name }}"
|
||||||
|
flat: true
|
||||||
|
mode: "0644"
|
||||||
|
|
||||||
|
- name: Include kubeconfig merge tasks
|
||||||
|
ansible.builtin.include_tasks: merge-kubeconfig.yml
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
# Kubeconfig merging tasks
|
||||||
|
|
||||||
|
- name: Check if main kubeconfig exists
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ local_home }}/.kube/config"
|
||||||
|
register: main_kubeconfig
|
||||||
|
|
||||||
|
- name: Create backup of existing kubeconfig
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.copy:
|
||||||
|
src: "{{ local_home }}/.kube/config"
|
||||||
|
dest: "{{ local_home }}/.kube/config.backup.{{ ansible_date_time.epoch }}"
|
||||||
|
mode: "0644"
|
||||||
|
when: main_kubeconfig.stat.exists
|
||||||
|
|
||||||
|
- name: Read new cluster kubeconfig
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: "{{ local_home }}/.kube/config-{{ cluster_name }}"
|
||||||
|
register: new_kubeconfig_content
|
||||||
|
|
||||||
|
- name: Parse new kubeconfig
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
new_kubeconfig: "{{ new_kubeconfig_content.content | b64decode | from_yaml }}"
|
||||||
|
|
||||||
|
- name: Update cluster name in kubeconfig
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
updated_kubeconfig:
|
||||||
|
apiVersion: "{{ new_kubeconfig.apiVersion }}"
|
||||||
|
kind: "{{ new_kubeconfig.kind }}"
|
||||||
|
clusters:
|
||||||
|
- name: "{{ cluster_name }}"
|
||||||
|
cluster: "{{ new_kubeconfig.clusters[0].cluster }}"
|
||||||
|
contexts:
|
||||||
|
- name: "{{ cluster_name }}-admin"
|
||||||
|
context:
|
||||||
|
cluster: "{{ cluster_name }}"
|
||||||
|
user: "{{ cluster_name }}-admin"
|
||||||
|
users:
|
||||||
|
- name: "{{ cluster_name }}-admin"
|
||||||
|
user: "{{ new_kubeconfig.users[0].user }}"
|
||||||
|
current-context: "{{ cluster_name }}-admin"
|
||||||
|
|
||||||
|
- name: Merge with existing kubeconfig or create new one
|
||||||
|
delegate_to: localhost
|
||||||
|
block:
|
||||||
|
- name: Read existing kubeconfig
|
||||||
|
ansible.builtin.slurp:
|
||||||
|
src: "{{ local_home }}/.kube/config"
|
||||||
|
register: existing_kubeconfig_content
|
||||||
|
when: main_kubeconfig.stat.exists
|
||||||
|
|
||||||
|
- name: Parse existing kubeconfig
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
existing_kubeconfig: "{{ existing_kubeconfig_content.content | b64decode | from_yaml }}"
|
||||||
|
when: main_kubeconfig.stat.exists
|
||||||
|
|
||||||
|
- name: Merge kubeconfigs
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
merged_kubeconfig:
|
||||||
|
apiVersion: "{{ existing_kubeconfig.apiVersion | default('v1') }}"
|
||||||
|
kind: "{{ existing_kubeconfig.kind | default('Config') }}"
|
||||||
|
clusters: "{{ (existing_kubeconfig.clusters | default([])) + updated_kubeconfig.clusters }}"
|
||||||
|
contexts: "{{ (existing_kubeconfig.contexts | default([])) + updated_kubeconfig.contexts }}"
|
||||||
|
users: "{{ (existing_kubeconfig.users | default([])) + updated_kubeconfig.users }}"
|
||||||
|
current-context: "{{ updated_kubeconfig['current-context'] }}"
|
||||||
|
when: main_kubeconfig.stat.exists
|
||||||
|
|
||||||
|
- name: Use new kubeconfig as merged config
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
merged_kubeconfig: "{{ updated_kubeconfig }}"
|
||||||
|
when: not main_kubeconfig.stat.exists
|
||||||
|
|
||||||
|
- name: Write merged kubeconfig
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.copy:
|
||||||
|
content: "{{ merged_kubeconfig | to_nice_yaml }}"
|
||||||
|
dest: "{{ local_home }}/.kube/config"
|
||||||
|
mode: "0644"
|
||||||
|
owner: "{{ local_user }}"
|
||||||
|
|
||||||
|
- name: Display available contexts
|
||||||
|
delegate_to: localhost
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: |
|
||||||
|
Kubeconfig updated successfully!
|
||||||
|
|
||||||
|
Available contexts:
|
||||||
|
{% for context in merged_kubeconfig.contexts %}
|
||||||
|
- {{ context.name }}
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
Current context: {{ merged_kubeconfig['current-context'] }}
|
||||||
|
|
||||||
|
To switch contexts, use:
|
||||||
|
kubectl config use-context <context-name>
|
||||||
|
|
||||||
|
To list all contexts:
|
||||||
|
kubectl config get-contexts
|
||||||
@@ -74,43 +74,3 @@
|
|||||||
- name: 7 Install containerd
|
- name: 7 Install containerd
|
||||||
ansible.builtin.include_role:
|
ansible.builtin.include_role:
|
||||||
name: containerd
|
name: containerd
|
||||||
|
|
||||||
# - name: Create kubelet config directory
|
|
||||||
# ansible.builtin.file:
|
|
||||||
# path: /var/lib/kubelet
|
|
||||||
# state: directory
|
|
||||||
# owner: root
|
|
||||||
# group: root
|
|
||||||
# mode: '0755'
|
|
||||||
|
|
||||||
# - name: Create initial kubelet config file
|
|
||||||
# ansible.builtin.copy:
|
|
||||||
# dest: /var/lib/kubelet/config.yaml
|
|
||||||
# owner: root
|
|
||||||
# group: root
|
|
||||||
# mode: '0644'
|
|
||||||
# content: |
|
|
||||||
# apiVersion: kubelet.config.k8s.io/v1beta1
|
|
||||||
# kind: KubeletConfiguration
|
|
||||||
# cgroupDriver: systemd
|
|
||||||
# containerRuntimeEndpoint: unix:///run/containerd/containerd.sock
|
|
||||||
|
|
||||||
# - name: Install CNI plugins via dnf
|
|
||||||
# ansible.builtin.dnf:
|
|
||||||
# name: containernetworking-plugins
|
|
||||||
# state: present
|
|
||||||
|
|
||||||
# - name: Verify CNI plugins installation
|
|
||||||
# ansible.builtin.shell: ls -la /opt/cni/bin/ || echo "CNI plugins not found in /opt/cni/bin/"
|
|
||||||
# register: cni_plugins
|
|
||||||
# ignore_errors: true
|
|
||||||
|
|
||||||
# - name: Display installed CNI plugins
|
|
||||||
# ansible.builtin.debug:
|
|
||||||
# msg: "CNI plugins status: {{ cni_plugins.stdout }}"
|
|
||||||
|
|
||||||
# - name: Enable kubelet service (but don't start yet)
|
|
||||||
# ansible.builtin.systemd:
|
|
||||||
# name: kubelet
|
|
||||||
# enabled: true
|
|
||||||
# state: stopped
|
|
||||||
|
|||||||
12
ansible/playbooks/roles/traefik-manager/defaults/main.yml
Normal file
12
ansible/playbooks/roles/traefik-manager/defaults/main.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
# Default variables for traefik-manager role
|
||||||
|
|
||||||
|
# Traefik Configuration
|
||||||
|
traefik_config_dir: "/etc/traefik"
|
||||||
|
traefik_host: "{{ traefik_server | default(groups['traefik_servers'][0] | default('localhost')) }}"
|
||||||
|
cluster_api_port: 6443
|
||||||
|
|
||||||
|
# Cluster Configuration (to be provided by calling role)
|
||||||
|
# cluster_name: "fastpass"
|
||||||
|
# cluster_endpoint: "fastpass.local.mk-labs.cloud"
|
||||||
|
# control_plane_nodes: ["space-mountain", "big-thunder-mountain", "splash-mountain"]
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
---
|
||||||
|
# Handlers for traefik-manager role
|
||||||
|
|
||||||
|
- name: reload traefik
|
||||||
|
ansible.builtin.systemd:
|
||||||
|
name: traefik
|
||||||
|
state: reloaded
|
||||||
|
delegate_to: "{{ traefik_host }}"
|
||||||
45
ansible/playbooks/roles/traefik-manager/tasks/main.yml
Normal file
45
ansible/playbooks/roles/traefik-manager/tasks/main.yml
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
---
|
||||||
|
# role: traefik-manager
|
||||||
|
# description: Reusable role for managing Traefik load balancer configuration
|
||||||
|
# author: mk-labs
|
||||||
|
# version: 1.0.0
|
||||||
|
|
||||||
|
- name: Create Traefik configuration directory
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ traefik_config_dir }}/dynamic"
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
delegate_to: "{{ traefik_host }}"
|
||||||
|
|
||||||
|
- name: Generate Traefik TCP router configuration for Kubernetes API
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: k8s-api-router.yml.j2
|
||||||
|
dest: "{{ traefik_config_dir }}/dynamic/{{ cluster_name }}-api.yml"
|
||||||
|
mode: "0644"
|
||||||
|
delegate_to: "{{ traefik_host }}"
|
||||||
|
notify: reload traefik
|
||||||
|
|
||||||
|
- name: Generate Traefik service configuration for control plane nodes
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: k8s-api-service.yml.j2
|
||||||
|
dest: "{{ traefik_config_dir }}/dynamic/{{ cluster_name }}-service.yml"
|
||||||
|
mode: "0644"
|
||||||
|
delegate_to: "{{ traefik_host }}"
|
||||||
|
notify: reload traefik
|
||||||
|
|
||||||
|
- name: Verify Traefik configuration syntax
|
||||||
|
ansible.builtin.command: |
|
||||||
|
traefik --configfile={{ traefik_config_dir }}/traefik.yml --dry-run
|
||||||
|
delegate_to: "{{ traefik_host }}"
|
||||||
|
register: traefik_syntax_check
|
||||||
|
failed_when: traefik_syntax_check.rc != 0
|
||||||
|
changed_when: false
|
||||||
|
|
||||||
|
- name: Display Traefik configuration status
|
||||||
|
ansible.builtin.debug:
|
||||||
|
msg: |
|
||||||
|
✅ Traefik configuration created successfully:
|
||||||
|
- Router: {{ cluster_name }}-api
|
||||||
|
- Service: {{ cluster_name }}-backend
|
||||||
|
- Endpoint: {{ cluster_endpoint }}:{{ cluster_api_port }}
|
||||||
|
- Backend nodes: {{ control_plane_nodes | join(', ') }}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
# Traefik TCP Router for {{ cluster_name }} Kubernetes API
|
||||||
|
tcp:
|
||||||
|
routers:
|
||||||
|
{{ cluster_name }}-api:
|
||||||
|
rule: "HostSNI(`{{ cluster_endpoint }}`)"
|
||||||
|
service: "{{ cluster_name }}-backend"
|
||||||
|
tls:
|
||||||
|
passthrough: true
|
||||||
|
entryPoints:
|
||||||
|
- "k8s-api"
|
||||||
|
|
||||||
|
services:
|
||||||
|
{{ cluster_name }}-backend:
|
||||||
|
loadBalancer:
|
||||||
|
servers:
|
||||||
|
{% for node in control_plane_nodes %}
|
||||||
|
- address: "{{ hostvars[node]['ansible_default_ipv4']['address'] }}:{{ cluster_api_port }}"
|
||||||
|
{% endfor %}
|
||||||
|
healthCheck:
|
||||||
|
path: "/healthz"
|
||||||
|
interval: "10s"
|
||||||
|
timeout: "3s"
|
||||||
20
ansible/playbooks/tasks/add_technitium_dns_entry.yml
Normal file
20
ansible/playbooks/tasks/add_technitium_dns_entry.yml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
# Reusable task file for adding Technitium DNS entries
|
||||||
|
# This replaces the standalone playbook and can be imported into any playbook
|
||||||
|
|
||||||
|
# - name: Display cluster_name
|
||||||
|
# ansible.builtin.debug:
|
||||||
|
# msg: "{{ host_name }} - {{ ip_address }} - {{ vault_technitium_api_key }}"
|
||||||
|
|
||||||
|
- name: Create DNS A Record entry for {{ host_name }}
|
||||||
|
delegate_to: localhost
|
||||||
|
effectivelywild.technitium_dns.technitium_dns_add_record:
|
||||||
|
api_url: "http://{{ dns_server }}.{{ base_domain }}"
|
||||||
|
api_token: "{{ vault_technitium_api_key }}"
|
||||||
|
zone: "{{ base_domain }}"
|
||||||
|
name: "{{ host_name }}.{{ base_domain }}"
|
||||||
|
type: "A"
|
||||||
|
ipAddress: "{{ ip_address }}"
|
||||||
|
ptr: true
|
||||||
|
ttl: 360
|
||||||
|
validate_certs: false
|
||||||
11
ansible/playbooks/test-dns-cname.yml
Normal file
11
ansible/playbooks/test-dns-cname.yml
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
---
|
||||||
|
- name: Test DNS CNAME Creation
|
||||||
|
hosts: fastpass_control_plane[0]
|
||||||
|
gather_facts: false
|
||||||
|
tasks:
|
||||||
|
- name: Test DNS CNAME entry creation
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: dns-manager
|
||||||
|
vars:
|
||||||
|
cluster_endpoint: "{{ control_plane_endpoint }}"
|
||||||
|
cluster_cname_target: "{{ traefik_server }}.{{ base_domain }}"
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
# requirements.yml
|
# requirements.yml
|
||||||
|
---
|
||||||
collections:
|
collections:
|
||||||
- name: community.general
|
- name: community.general
|
||||||
version: 11.1.0
|
version: 11.1.0
|
||||||
|
|
||||||
- name: nccurry.openshift
|
# - name: nccurry.openshift
|
||||||
version: 1.4.0
|
# version: 1.4.0
|
||||||
|
|
||||||
- name: somaz94.ansible_k8s_iac_tool
|
- name: somaz94.ansible_k8s_iac_tool
|
||||||
version: 1.1.6
|
version: 1.1.6
|
||||||
|
|
||||||
- name: prometheus.prometheus
|
# - name: prometheus.prometheus
|
||||||
version: 0.27.0
|
# version: 0.27.0
|
||||||
|
|
||||||
|
- name: kubernetes.core
|
||||||
82
ansible/scripts/migrate-dns-references.sh
Normal file
82
ansible/scripts/migrate-dns-references.sh
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Migration script to update DNS entry references
|
||||||
|
# This script helps migrate from the old add_technitium_dns_entry.yml to the new modular approach
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
print_status() {
|
||||||
|
local status=$1
|
||||||
|
local message=$2
|
||||||
|
case $status in
|
||||||
|
"INFO")
|
||||||
|
echo -e "${BLUE}ℹ️ INFO${NC}: $message"
|
||||||
|
;;
|
||||||
|
"SUCCESS")
|
||||||
|
echo -e "${GREEN}✅ SUCCESS${NC}: $message"
|
||||||
|
;;
|
||||||
|
"ERROR")
|
||||||
|
echo -e "${RED}❌ ERROR${NC}: $message"
|
||||||
|
;;
|
||||||
|
"WARN")
|
||||||
|
echo -e "${YELLOW}⚠️ WARN${NC}: $message"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
print_status "INFO" "Migrating DNS entry references to modular approach..."
|
||||||
|
|
||||||
|
# Search for references to the old playbook
|
||||||
|
OLD_PLAYBOOK="add_technitium_dns_entry.yml"
|
||||||
|
NEW_PLAYBOOK="add_dns_entry.yml"
|
||||||
|
|
||||||
|
# Find all YAML files that might reference the old playbook
|
||||||
|
YAML_FILES=$(find . -name "*.yml" -type f | grep -v ".git")
|
||||||
|
|
||||||
|
FOUND_REFERENCES=0
|
||||||
|
|
||||||
|
for file in $YAML_FILES; do
|
||||||
|
if grep -q "$OLD_PLAYBOOK" "$file" 2>/dev/null; then
|
||||||
|
print_status "WARN" "Found reference in: $file"
|
||||||
|
FOUND_REFERENCES=$((FOUND_REFERENCES + 1))
|
||||||
|
|
||||||
|
# Show the context
|
||||||
|
echo " Context:"
|
||||||
|
grep -n -B2 -A2 "$OLD_PLAYBOOK" "$file" | sed 's/^/ /'
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $FOUND_REFERENCES -eq 0 ]; then
|
||||||
|
print_status "SUCCESS" "No references to $OLD_PLAYBOOK found"
|
||||||
|
else
|
||||||
|
print_status "INFO" "Found $FOUND_REFERENCES references to migrate"
|
||||||
|
print_status "INFO" "Migration options:"
|
||||||
|
echo ""
|
||||||
|
echo "1. Replace playbook imports:"
|
||||||
|
echo " OLD: - import_playbook: $OLD_PLAYBOOK"
|
||||||
|
echo " NEW: - import_playbook: $NEW_PLAYBOOK"
|
||||||
|
echo ""
|
||||||
|
echo "2. Use task includes in roles:"
|
||||||
|
echo " - ansible.builtin.include_tasks: tasks/add_technitium_dns_entry.yml"
|
||||||
|
echo ""
|
||||||
|
echo "3. Use the dns-manager role:"
|
||||||
|
echo " - ansible.builtin.include_role:"
|
||||||
|
echo " name: dns-manager"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the old playbook exists and suggest backup
|
||||||
|
if [ -f "playbooks/$OLD_PLAYBOOK" ]; then
|
||||||
|
print_status "INFO" "Old playbook exists at: playbooks/$OLD_PLAYBOOK"
|
||||||
|
print_status "INFO" "Consider backing it up before removing:"
|
||||||
|
echo " mv playbooks/$OLD_PLAYBOOK playbooks/${OLD_PLAYBOOK}.backup"
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_status "SUCCESS" "Migration analysis complete"
|
||||||
114
ansible/scripts/setup-cluster-network.sh
Normal file
114
ansible/scripts/setup-cluster-network.sh
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# FastPass Homelab - Cluster Network Setup Script
|
||||||
|
# This script sets up DNS (via Technitium) and load balancer configuration for any Kubernetes cluster
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Function to print colored output
|
||||||
|
print_status() {
|
||||||
|
local status=$1
|
||||||
|
local message=$2
|
||||||
|
case $status in
|
||||||
|
"INFO")
|
||||||
|
echo -e "${BLUE}ℹ️ INFO${NC}: $message"
|
||||||
|
;;
|
||||||
|
"SUCCESS")
|
||||||
|
echo -e "${GREEN}✅ SUCCESS${NC}: $message"
|
||||||
|
;;
|
||||||
|
"ERROR")
|
||||||
|
echo -e "${RED}❌ ERROR${NC}: $message"
|
||||||
|
;;
|
||||||
|
"WARN")
|
||||||
|
echo -e "${YELLOW}⚠️ WARN${NC}: $message"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage function
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 <cluster_name> <cluster_endpoint> <control_plane_group>"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 fastpass fastpass.local.mk-labs.cloud fastpass_control_plane"
|
||||||
|
echo " $0 hub hub.local.mk-labs.cloud hub_cluster"
|
||||||
|
echo " $0 internal internal.local.mk-labs.cloud internal_cluster"
|
||||||
|
echo ""
|
||||||
|
echo "This script will:"
|
||||||
|
echo " 1. Create DNS entry for the cluster endpoint"
|
||||||
|
echo " 2. Configure Traefik load balancer"
|
||||||
|
echo " 3. Test connectivity"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check arguments
|
||||||
|
if [ $# -ne 3 ]; then
|
||||||
|
print_status "ERROR" "Invalid number of arguments"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
CLUSTER_NAME=$1
|
||||||
|
CLUSTER_ENDPOINT=$2
|
||||||
|
CONTROL_PLANE_GROUP=$3
|
||||||
|
|
||||||
|
print_status "INFO" "Setting up network for cluster: $CLUSTER_NAME"
|
||||||
|
print_status "INFO" "Endpoint: $CLUSTER_ENDPOINT"
|
||||||
|
print_status "INFO" "Control plane group: $CONTROL_PLANE_GROUP"
|
||||||
|
|
||||||
|
# Check if inventory file exists
|
||||||
|
if [ ! -f "inventory.yml" ]; then
|
||||||
|
print_status "ERROR" "inventory.yml not found. Please run from ansible directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create temporary playbook
|
||||||
|
TEMP_PLAYBOOK=$(mktemp /tmp/cluster-network-setup-XXXXXX.yml)
|
||||||
|
cat > "$TEMP_PLAYBOOK" << EOF
|
||||||
|
---
|
||||||
|
- name: Setup network infrastructure for $CLUSTER_NAME
|
||||||
|
hosts: ${CONTROL_PLANE_GROUP}[0]
|
||||||
|
gather_facts: true
|
||||||
|
tasks:
|
||||||
|
- name: Setup cluster network infrastructure
|
||||||
|
ansible.builtin.include_role:
|
||||||
|
name: cluster-network-setup
|
||||||
|
vars:
|
||||||
|
cluster_name: "$CLUSTER_NAME"
|
||||||
|
cluster_endpoint: "$CLUSTER_ENDPOINT"
|
||||||
|
cluster_vip: "{{ ansible_default_ipv4.address }}"
|
||||||
|
control_plane_nodes: "{{ groups['$CONTROL_PLANE_GROUP'] }}"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
print_status "INFO" "Running network setup playbook..."
|
||||||
|
|
||||||
|
# Run the network setup
|
||||||
|
if ansible-playbook -i inventory.yml "$TEMP_PLAYBOOK"; then
|
||||||
|
print_status "SUCCESS" "Network setup completed for $CLUSTER_NAME"
|
||||||
|
|
||||||
|
# Test connectivity
|
||||||
|
print_status "INFO" "Testing connectivity to $CLUSTER_ENDPOINT:6443..."
|
||||||
|
if timeout 10 bash -c "</dev/tcp/$CLUSTER_ENDPOINT/6443"; then
|
||||||
|
print_status "SUCCESS" "Connectivity test passed"
|
||||||
|
else
|
||||||
|
print_status "WARN" "Connectivity test failed - may need time to propagate"
|
||||||
|
fi
|
||||||
|
|
||||||
|
print_status "INFO" "Network setup complete. You can now:"
|
||||||
|
echo " 1. Deploy your cluster"
|
||||||
|
echo " 2. Test with: kubectl --server=https://$CLUSTER_ENDPOINT:6443 cluster-info"
|
||||||
|
|
||||||
|
else
|
||||||
|
print_status "ERROR" "Network setup failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Cleanup
|
||||||
|
rm -f "$TEMP_PLAYBOOK"
|
||||||
91
ansible/scripts/setup-kubeconfig.sh
Normal file
91
ansible/scripts/setup-kubeconfig.sh
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# FastPass Homelab - Kubeconfig Setup Script
|
||||||
|
# This script makes it easy to add any cluster's kubeconfig to your local config
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Function to print colored output
|
||||||
|
print_status() {
|
||||||
|
local status=$1
|
||||||
|
local message=$2
|
||||||
|
case $status in
|
||||||
|
"INFO")
|
||||||
|
echo -e "${BLUE}ℹ️ INFO${NC}: $message"
|
||||||
|
;;
|
||||||
|
"SUCCESS")
|
||||||
|
echo -e "${GREEN}✅ SUCCESS${NC}: $message"
|
||||||
|
;;
|
||||||
|
"ERROR")
|
||||||
|
echo -e "${RED}❌ ERROR${NC}: $message"
|
||||||
|
;;
|
||||||
|
"WARN")
|
||||||
|
echo -e "${YELLOW}⚠️ WARN${NC}: $message"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage function
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 <cluster_name> <host_group>"
|
||||||
|
echo ""
|
||||||
|
echo "Examples:"
|
||||||
|
echo " $0 fastpass fastpass_control_plane[0]"
|
||||||
|
echo " $0 hub hub_cluster"
|
||||||
|
echo " $0 internal internal_cluster[0]"
|
||||||
|
echo ""
|
||||||
|
echo "Available clusters in your homelab:"
|
||||||
|
echo " - fastpass (FastPass Kubernetes cluster)"
|
||||||
|
echo " - hub (OpenShift Hub cluster)"
|
||||||
|
echo " - internal (Internal OpenShift cluster)"
|
||||||
|
echo ""
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check arguments
|
||||||
|
if [ $# -ne 2 ]; then
|
||||||
|
print_status "ERROR" "Invalid number of arguments"
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
CLUSTER_NAME=$1
|
||||||
|
HOST_GROUP=$2
|
||||||
|
|
||||||
|
print_status "INFO" "Setting up kubeconfig for cluster: $CLUSTER_NAME"
|
||||||
|
print_status "INFO" "Target hosts: $HOST_GROUP"
|
||||||
|
|
||||||
|
# Check if inventory file exists
|
||||||
|
if [ ! -f "inventory.yml" ]; then
|
||||||
|
print_status "ERROR" "inventory.yml not found. Please run from ansible directory."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run the kubeconfig setup
|
||||||
|
print_status "INFO" "Running Ansible playbook..."
|
||||||
|
|
||||||
|
ansible-playbook -i inventory.yml \
|
||||||
|
playbooks/examples/multi-cluster-kubeconfig.yml \
|
||||||
|
--limit "$HOST_GROUP" \
|
||||||
|
-e "target_cluster_hosts=$HOST_GROUP" \
|
||||||
|
-e "target_cluster_name=$CLUSTER_NAME" \
|
||||||
|
--tags kubeconfig
|
||||||
|
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
print_status "SUCCESS" "Kubeconfig setup completed for $CLUSTER_NAME"
|
||||||
|
print_status "INFO" "You can now use: kubectl config use-context ${CLUSTER_NAME}-admin"
|
||||||
|
|
||||||
|
# Show available contexts
|
||||||
|
echo ""
|
||||||
|
print_status "INFO" "Available contexts:"
|
||||||
|
kubectl config get-contexts 2>/dev/null || print_status "WARN" "kubectl not found or kubeconfig not accessible"
|
||||||
|
else
|
||||||
|
print_status "ERROR" "Kubeconfig setup failed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
0
ansible/scripts/test-fastpass-deployment.sh
Executable file → Normal file
0
ansible/scripts/test-fastpass-deployment.sh
Executable file → Normal file
9
ansible/test-fastpass-role.yml
Normal file
9
ansible/test-fastpass-role.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
- name: Test FastPass First Control Plane Role
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: true
|
||||||
|
vars:
|
||||||
|
cluster_name: "fastpass"
|
||||||
|
kubernetes_services_control_plane: []
|
||||||
|
roles:
|
||||||
|
- role: playbooks/roles/fastpass-first-control-plane
|
||||||
161
calendar-sync.applescript
Normal file
161
calendar-sync.applescript
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
(*
|
||||||
|
Calendar Sync Script
|
||||||
|
|
||||||
|
Synchronizes calendar events between two calendar accounts for the current day.
|
||||||
|
Reads events from a source calendar and mirrors them to a destination calendar,
|
||||||
|
including removal of events that no longer exist in the source.
|
||||||
|
*)
|
||||||
|
|
||||||
|
-- Configuration Properties
|
||||||
|
property sourceAccountName : "Work Account"
|
||||||
|
property sourceCalendarName : "Main Calendar"
|
||||||
|
property destinationAccountName : "Personal Account"
|
||||||
|
property destinationCalendarName : "Synced Events"
|
||||||
|
property enableLogging : true
|
||||||
|
property enableDebugMode : false
|
||||||
|
|
||||||
|
-- Logging levels
|
||||||
|
property LOG_ERROR : 1
|
||||||
|
property LOG_WARNING : 2
|
||||||
|
property LOG_INFO : 3
|
||||||
|
property LOG_DEBUG : 4
|
||||||
|
|
||||||
|
-- Global variables for tracking sync state
|
||||||
|
global syncResults
|
||||||
|
global errorList
|
||||||
|
|
||||||
|
-- Initialize sync results record
|
||||||
|
on initializeSyncResults()
|
||||||
|
set syncResults to {eventsCreated:0, eventsUpdated:0, eventsRemoved:0, eventsSkipped:0, errors:{}}
|
||||||
|
set errorList to {}
|
||||||
|
end initializeSyncResults
|
||||||
|
|
||||||
|
-- Main entry point
|
||||||
|
on run
|
||||||
|
try
|
||||||
|
-- Initialize logging and sync tracking
|
||||||
|
initializeSyncResults()
|
||||||
|
logMessage("Starting Calendar Sync", LOG_INFO)
|
||||||
|
|
||||||
|
-- Display configuration
|
||||||
|
logMessage("Source: " & sourceAccountName & " -> " & sourceCalendarName, LOG_INFO)
|
||||||
|
logMessage("Destination: " & destinationAccountName & " -> " & destinationCalendarName, LOG_INFO)
|
||||||
|
|
||||||
|
-- TODO: Implement main sync workflow
|
||||||
|
logMessage("Calendar sync setup complete", LOG_INFO)
|
||||||
|
|
||||||
|
on error errorMessage number errorNumber
|
||||||
|
handleError("Main execution error: " & errorMessage, errorNumber)
|
||||||
|
end try
|
||||||
|
end run
|
||||||
|
|
||||||
|
-- Logging and Error Handling Framework
|
||||||
|
|
||||||
|
-- Log a message with specified level
|
||||||
|
on logMessage(message, level)
|
||||||
|
if not enableLogging then return
|
||||||
|
|
||||||
|
set levelText to getLevelText(level)
|
||||||
|
set timestamp to (current date) as string
|
||||||
|
set logEntry to "[" & timestamp & "] " & levelText & ": " & message
|
||||||
|
|
||||||
|
-- Display to user (can be modified to write to file if needed)
|
||||||
|
if level ≤ LOG_WARNING or enableDebugMode then
|
||||||
|
display notification message with title "Calendar Sync " & levelText
|
||||||
|
end if
|
||||||
|
|
||||||
|
-- Always log errors and warnings to console
|
||||||
|
if level ≤ LOG_WARNING then
|
||||||
|
log logEntry
|
||||||
|
else if enableDebugMode then
|
||||||
|
log logEntry
|
||||||
|
end if
|
||||||
|
end logMessage
|
||||||
|
|
||||||
|
-- Get text representation of log level
|
||||||
|
on getLevelText(level)
|
||||||
|
if level = LOG_ERROR then
|
||||||
|
return "ERROR"
|
||||||
|
else if level = LOG_WARNING then
|
||||||
|
return "WARNING"
|
||||||
|
else if level = LOG_INFO then
|
||||||
|
return "INFO"
|
||||||
|
else if level = LOG_DEBUG then
|
||||||
|
return "DEBUG"
|
||||||
|
else
|
||||||
|
return "UNKNOWN"
|
||||||
|
end if
|
||||||
|
end getLevelText
|
||||||
|
|
||||||
|
-- Handle errors with logging and user feedback
|
||||||
|
on handleError(errorMessage, errorNumber)
|
||||||
|
set fullErrorMessage to errorMessage & " (Error " & errorNumber & ")"
|
||||||
|
|
||||||
|
-- Log the error
|
||||||
|
logMessage(fullErrorMessage, LOG_ERROR)
|
||||||
|
|
||||||
|
-- Add to error list for reporting
|
||||||
|
set end of errorList to fullErrorMessage
|
||||||
|
|
||||||
|
-- Display user-friendly error dialog
|
||||||
|
display dialog "Calendar Sync Error: " & errorMessage buttons {"OK"} default button "OK" with icon stop
|
||||||
|
end handleError
|
||||||
|
|
||||||
|
-- Display progress to user
|
||||||
|
on displayProgress(currentItem, totalItems, itemDescription)
|
||||||
|
if not enableLogging then return
|
||||||
|
|
||||||
|
set progressPercent to round ((currentItem / totalItems) * 100)
|
||||||
|
set progressMessage to "Processing " & itemDescription & " (" & currentItem & " of " & totalItems & " - " & progressPercent & "%)"
|
||||||
|
|
||||||
|
logMessage(progressMessage, LOG_INFO)
|
||||||
|
end displayProgress
|
||||||
|
|
||||||
|
-- Display final sync summary
|
||||||
|
on showSyncSummary()
|
||||||
|
set summaryMessage to "Sync Complete!" & return & return
|
||||||
|
set summaryMessage to summaryMessage & "Events Created: " & (eventsCreated of syncResults) & return
|
||||||
|
set summaryMessage to summaryMessage & "Events Updated: " & (eventsUpdated of syncResults) & return
|
||||||
|
set summaryMessage to summaryMessage & "Events Removed: " & (eventsRemoved of syncResults) & return
|
||||||
|
set summaryMessage to summaryMessage & "Events Skipped: " & (eventsSkipped of syncResults) & return
|
||||||
|
|
||||||
|
if (count of errorList) > 0 then
|
||||||
|
set summaryMessage to summaryMessage & return & "Errors encountered: " & (count of errorList)
|
||||||
|
end if
|
||||||
|
|
||||||
|
logMessage(summaryMessage, LOG_INFO)
|
||||||
|
display dialog summaryMessage buttons {"OK"} default button "OK" with icon note
|
||||||
|
end showSyncSummary
|
||||||
|
|
||||||
|
-- Validate configuration before starting sync
|
||||||
|
on validateConfiguration()
|
||||||
|
logMessage("Validating configuration...", LOG_DEBUG)
|
||||||
|
|
||||||
|
-- Check that required properties are set
|
||||||
|
if sourceAccountName = "" or sourceCalendarName = "" then
|
||||||
|
handleError("Source calendar configuration is incomplete", -1)
|
||||||
|
return false
|
||||||
|
end if
|
||||||
|
|
||||||
|
if destinationAccountName = "" or destinationCalendarName = "" then
|
||||||
|
handleError("Destination calendar configuration is incomplete", -2)
|
||||||
|
return false
|
||||||
|
end if
|
||||||
|
|
||||||
|
logMessage("Configuration validation passed", LOG_DEBUG)
|
||||||
|
return true
|
||||||
|
end validateConfiguration
|
||||||
|
|
||||||
|
-- Utility function to get current date for today's events
|
||||||
|
on getCurrentDate()
|
||||||
|
return current date
|
||||||
|
end getCurrentDate
|
||||||
|
|
||||||
|
-- Utility function to create date range for current day
|
||||||
|
on getCurrentDayRange()
|
||||||
|
set today to getCurrentDate()
|
||||||
|
set startOfDay to date (short date string of today)
|
||||||
|
set endOfDay to startOfDay + (24 * hours) - 1
|
||||||
|
|
||||||
|
return {startDate:startOfDay, endDate:endOfDay}
|
||||||
|
end getCurrentDayRange
|
||||||
0
infra-config/04-vm-templates/fedora-42/fedora-42-large-plus.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-large-plus.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-large.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-large.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-medium.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-medium.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-small.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-small.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-xlarge-plus.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-xlarge-plus.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-xlarge.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42-xlarge.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42.pkr.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/fedora-42.pkr.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/variables.pkrvars-xlarge.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/fedora-42/variables.pkrvars-xlarge.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/ubuntu-24.04.pkr.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/ubuntu-24.04.pkr.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/ubuntu-24.04.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/ubuntu-24.04.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-large-plus.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-large-plus.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-large.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-large.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-medium.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-medium.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-small.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-small.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-xlarge-plus.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-xlarge-plus.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-xlarge.pkrvars.hcl
Executable file → Normal file
0
infra-config/04-vm-templates/ubuntu-24.04.03/vm-xlarge.pkrvars.hcl
Executable file → Normal file
@@ -38,6 +38,28 @@ May refactor folder structure to:
|
|||||||
ansible-vault create vault
|
ansible-vault create vault
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To set up the virtual environment, follow these steps:
|
||||||
|
|
||||||
|
1. Create a virtual environment named `venv-ansible`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 -m venv ~/venv-ansible
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Activate the virtual environment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source ~/venv-ansible/bin/activate
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Install the required packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pip install -r </path/to/your/repo>/requirements.txt
|
||||||
|
```
|
||||||
|
ansible-galaxy collection install -r ansible/requirements.yml
|
||||||
|
|
||||||
|
|
||||||
- Modify ansible variables for your environment
|
- Modify ansible variables for your environment
|
||||||
|
|
||||||
## [Network](00-network/README.md) *Manual*
|
## [Network](00-network/README.md) *Manual*
|
||||||
@@ -73,7 +95,7 @@ May refactor folder structure to:
|
|||||||
ssh infra01
|
ssh infra01
|
||||||
|
|
||||||
cd homelab
|
cd homelab
|
||||||
ansible-galaxy collection install -r requirements.yml
|
ansible-galaxy collection install -r ansible/requirements.yml
|
||||||
ansible-playbook -i inventory.yml 10-sno-hub-cluster/install.yml
|
ansible-playbook -i inventory.yml 10-sno-hub-cluster/install.yml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
apiVersion: v2
|
|
||||||
name: external-secrets
|
|
||||||
description: A Helm chart for Kubernetes
|
|
||||||
|
|
||||||
# A chart can be either an 'application' or a 'library' chart.
|
|
||||||
#
|
|
||||||
# Application charts are a collection of templates that can be packaged into versioned archives
|
|
||||||
# to be deployed.
|
|
||||||
#
|
|
||||||
# Library charts provide useful utilities or functions for the chart developer. They're included as
|
|
||||||
# a dependency of application charts to inject those utilities and functions into the rendering
|
|
||||||
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
|
|
||||||
type: application
|
|
||||||
|
|
||||||
# This is the chart version. This version number should be incremented each time you make changes
|
|
||||||
# to the chart and its templates, including the app version.
|
|
||||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
|
||||||
version: 0.1.0
|
|
||||||
|
|
||||||
# This is the version number of the application being deployed. This version number should be
|
|
||||||
# incremented each time you make changes to the application. Versions are not expected to
|
|
||||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
|
||||||
# It is recommended to use it with quotes.
|
|
||||||
appVersion: "0.16.1"
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
- name: external-secrets
|
|
||||||
version: "0.16.1"
|
|
||||||
repository: https://charts.external-secrets.io/
|
|
||||||
condition: external-secrets.enabled
|
|
||||||
4
tmp/acm-hub-bootstrap-old/.gitignore
vendored
4
tmp/acm-hub-bootstrap-old/.gitignore
vendored
@@ -1,4 +0,0 @@
|
|||||||
sealed-secrets-key.yaml
|
|
||||||
slack-token-key.yaml
|
|
||||||
*-private.yaml
|
|
||||||
eso-token-*.yaml
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
### Introduction
|
|
||||||
|
|
||||||
This repository is used to bootstrap the RHACM Hub cluster as well as hold the ACM configuration
|
|
||||||
I use in my homelab environment. It is referenced by the [cluster-config](https://github.com/gnunn-gitops/cluster-config) repo for the `local.hub` cluster's ACM applications (Hub, Policies and Observerability).
|
|
||||||
|
|
||||||
From the perspective of bootstrapping the Hub there are a couple of different ways to go. You could
|
|
||||||
manually install OpenShift GitOps and have it bootstrap everything on the Hub including RHACM. However while
|
|
||||||
I did consider that approach I'm using ACM to bootstrap my managed clusters and I wanted to use the exact same workflow
|
|
||||||
if I could for the Hub. This is because I wanted to avoid having to create a tweaked workflow just for the Hub.
|
|
||||||
|
|
||||||
### Bootstrap Process
|
|
||||||
|
|
||||||
The bootstrap process, encapsulated in the `bootstrap.sh` script, is as follows:
|
|
||||||
|
|
||||||
1. Install the RHACM operator and wait for it to complete
|
|
||||||
2. Install the MultiClusterHub custom resource and wait for it to be in the Running phase
|
|
||||||
3. Deploy all of the RHACM policies including the policy that deploys the OpenShift
|
|
||||||
GitOps operator with the bootstrap application
|
|
||||||
4. Label the Hub cluster, `local-cluster`, with the label `gitops=local.hub`. This trigger the
|
|
||||||
GitOps policy we deployed in step #3 to install OpenShift GitOps on the Hub cluster and
|
|
||||||
deploy the bootstrap application pointing to the repo and path needed for this cluster, i.e.
|
|
||||||
`local.home`
|
|
||||||
|
|
||||||
At this point the GitOps operator deploys everything the Hub cluster requires including storage, operators, etc
|
|
||||||
as well as other ACM components. In particular, the components that the script deployed (Hub + Policies) have
|
|
||||||
Argo applications that will take over managing these.
|
|
||||||
|
|
||||||
With the script bootstrapping the Hub because a one command affair. Once the command completes successfully
|
|
||||||
I walk away for 20-30 minutes while everything gets sorted out.
|
|
||||||
|
|
||||||
### Side-note on LVM Operator
|
|
||||||
|
|
||||||
If you are running a SNO cluster like I am and using the LVM Operator make sure that whatever device you are
|
|
||||||
using for storage with it is free. For example, if you are doing a reinstall of the hub (or other cluster), after
|
|
||||||
the cluster is provisioned but before you provision Day 2 ops ssh to the cluster and run `lsblk` to make sure
|
|
||||||
the device is empty with no partitions.
|
|
||||||
|
|
||||||
A reminder for future me. :)
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
LANG=C
|
|
||||||
SLEEP_SECONDS=30
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Installing RHACM Operator."
|
|
||||||
|
|
||||||
kustomize build github.com/redhat-cop/gitops-catalog/advanced-cluster-management/operator/overlays/release-2.9 | oc apply -f -
|
|
||||||
|
|
||||||
echo "Pause $SLEEP_SECONDS seconds for the creation of the rhacm-operator..."
|
|
||||||
sleep $SLEEP_SECONDS
|
|
||||||
|
|
||||||
echo "Waiting for operator to start"
|
|
||||||
until oc get deployment multiclusterhub-operator -n open-cluster-management
|
|
||||||
do
|
|
||||||
sleep 10;
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Installing the MultiClusterHub"
|
|
||||||
|
|
||||||
kustomize build github.com/redhat-cop/gitops-catalog/advanced-cluster-management/instance/base | oc apply -f -
|
|
||||||
|
|
||||||
echo "Waiting for hub to be installed"
|
|
||||||
|
|
||||||
until [[ $(oc get multiclusterhub multiclusterhub -n open-cluster-management -o jsonpath='{.status.phase}') == 'Running' ]]
|
|
||||||
do
|
|
||||||
echo "Waiting for hub, current status:"
|
|
||||||
oc get multiclusterhub multiclusterhub -n open-cluster-management
|
|
||||||
sleep 10
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Installing policies and initial secrets"
|
|
||||||
|
|
||||||
kustomize build bootstrap/secrets/base | oc apply -f -
|
|
||||||
kustomize build bootstrap/policies/overlays/default --enable-alpha-plugins | oc apply -f -
|
|
||||||
|
|
||||||
echo "Labeling cluster with 'gitops: local.home'"
|
|
||||||
oc label managedcluster local-cluster gitops=local.hub --overwrite=true
|
|
||||||
|
|
||||||
echo "Check policy compliance with the following command:"
|
|
||||||
echo " oc get policy -A"
|
|
||||||
|
|
||||||
echo "Once GitOps configuration is complete you may need to run the following to fix Unknown status\n"
|
|
||||||
echo " oc delete secret local-cluster-import -n local-cluster\n"
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Experimental, not used at the momentgit add
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
LANG=C
|
|
||||||
SLEEP_SECONDS=45
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "Installing GitOps Operator."
|
|
||||||
|
|
||||||
kustomize build ../../components/policies/gitops/base/manifests/gitops-subscription | oc apply -f -
|
|
||||||
|
|
||||||
echo "Pause $SLEEP_SECONDS seconds for the creation of the gitops-operator..."
|
|
||||||
sleep $SLEEP_SECONDS
|
|
||||||
|
|
||||||
echo "Waiting for operator to start"
|
|
||||||
until oc get deployment gitops-operator-controller-manager -n openshift-operators
|
|
||||||
do
|
|
||||||
sleep 5;
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Waiting for openshift-gitops namespace to be created"
|
|
||||||
until oc get ns openshift-gitops
|
|
||||||
do
|
|
||||||
sleep 5;
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Waiting for deployments to start"
|
|
||||||
until oc get deployment cluster -n openshift-gitops
|
|
||||||
do
|
|
||||||
sleep 5;
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Waiting for all pods to be created"
|
|
||||||
deployments=(cluster kam openshift-gitops-applicationset-controller openshift-gitops-redis openshift-gitops-repo-server openshift-gitops-server)
|
|
||||||
for i in "${deployments[@]}";
|
|
||||||
do
|
|
||||||
echo "Waiting for deployment $i";
|
|
||||||
oc rollout status deployment $i -n openshift-gitops
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "Apply overlay to override default instance"
|
|
||||||
# echo "Create default instance of gitops operator"
|
|
||||||
kustomize build ../../components/policies/gitops/base/manifests/gitops-instance/base |
|
|
||||||
yq -y ".spec.repo.env |= map(select(.name == \"INFRASTRUCTURE_ID\").value=\"$INFRASTRUCTURE_ID\")" |
|
|
||||||
yq -y ".spec.repo.env |= map(select(.name == \"CLUSTER_ID\").value=\"$CLUSTER_ID\")" |
|
|
||||||
yq -y ".spec.repo.env |= map(select(.name == \"CLUSTER_NAME\").value=\"$CLUSTER_NAME\")" |
|
|
||||||
yq -y ".spec.repo.env |= map(select(.name == \"SUB_DOMAIN\").value=\"$SUB_DOMAIN\")" |
|
|
||||||
oc apply -f -
|
|
||||||
|
|
||||||
sleep 10
|
|
||||||
echo "Waiting for all pods to redeploy"
|
|
||||||
deployments=(cluster kam openshift-gitops-applicationset-controller openshift-gitops-redis openshift-gitops-repo-server openshift-gitops-server)
|
|
||||||
for i in "${deployments[@]}";
|
|
||||||
do
|
|
||||||
echo "Waiting for deployment $i";
|
|
||||||
oc rollout status deployment $i -n openshift-gitops
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "GitOps Operator ready"
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
namespace: acm-policies
|
|
||||||
|
|
||||||
namespace: acm-policies
|
|
||||||
|
|
||||||
resources:
|
|
||||||
# - ../../../../components/policies/compliance/base
|
|
||||||
- ../../../../components/policies/cert-expiration/base
|
|
||||||
- ../../../../components/policies/gitops/base
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
Bootstrap tokens for ESO to access Doppler projects, note that these secrets are not in git.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
name: hub-secrets
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
resources:
|
|
||||||
- namespace.yaml
|
|
||||||
- hub-secrets-namespace.yaml
|
|
||||||
# Note these secrets are not stored in git and only applied during bootstrap process
|
|
||||||
# They are the tokens for accessing the Doppler secrets SaaS service where secrets are stored
|
|
||||||
- eso-token-cluster-push-secret.yaml
|
|
||||||
- eso-token-cluster-home-secret.yaml
|
|
||||||
- eso-token-cluster-hub-secret.yaml
|
|
||||||
- eso-token-cluster-rhdp-secret.yaml
|
|
||||||
- eso-token-cluster-microshift-secret.yaml
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Namespace
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
openshift.io/description: ACM Policies
|
|
||||||
openshift.io/display-name: ACM Policies
|
|
||||||
labels:
|
|
||||||
name: acm-policies
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
resources:
|
|
||||||
- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/operator/overlays/release-2.12
|
|
||||||
- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/instance/base
|
|
||||||
|
|
||||||
patches:
|
|
||||||
- patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/channel
|
|
||||||
value: 'release-2.13'
|
|
||||||
target:
|
|
||||||
kind: Subscription
|
|
||||||
name: advanced-cluster-management
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
kind: ConfigMap
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: observability-metrics-custom-allowlist
|
|
||||||
namespace: open-cluster-management-observability
|
|
||||||
data:
|
|
||||||
metrics_list.yaml: |
|
|
||||||
names:
|
|
||||||
- argocd_cluster_info
|
|
||||||
- argocd-server-metrics
|
|
||||||
- argocd_app_info
|
|
||||||
- argocd_app_sync_total
|
|
||||||
- argocd_app_reconcile_count
|
|
||||||
- argocd_app_reconcile_bucket
|
|
||||||
- argocd_app_k8s_request_total
|
|
||||||
- argocd_kubectl_exec_pending
|
|
||||||
- argocd-metrics
|
|
||||||
- argocd_cluster_api_resource_objects
|
|
||||||
- argocd_cluster_api_resources
|
|
||||||
- argocd_cluster_events_total
|
|
||||||
- argocd_git_request_total
|
|
||||||
- argocd_git_request_duration_seconds_bucket
|
|
||||||
- argocd-repo-server
|
|
||||||
- argocd_redis_request_total
|
|
||||||
- process_start_time_seconds
|
|
||||||
- workqueue_depth
|
|
||||||
- go_memstats_heap_alloc_bytes
|
|
||||||
- process_cpu_seconds_total
|
|
||||||
- go_goroutines
|
|
||||||
- go_gc_duration_seconds
|
|
||||||
- grpc_server_handled_total
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,46 +0,0 @@
|
|||||||
namespace: open-cluster-management-observability
|
|
||||||
|
|
||||||
generatorOptions:
|
|
||||||
disableNameSuffixHash: true
|
|
||||||
labels:
|
|
||||||
grafana-custom-dashboard: "true"
|
|
||||||
|
|
||||||
resources:
|
|
||||||
- github.com/redhat-cop/gitops-catalog/advanced-cluster-management/instance/observability
|
|
||||||
- custom-metrics-allowlist.yaml
|
|
||||||
|
|
||||||
configMapGenerator:
|
|
||||||
- name: gitops-dashboard
|
|
||||||
files:
|
|
||||||
- gitops.json=gitops-dashboard.json
|
|
||||||
|
|
||||||
patches:
|
|
||||||
- patch: |-
|
|
||||||
- op: replace
|
|
||||||
path: /spec/storageConfig/storageClass
|
|
||||||
value: lvms-vg1
|
|
||||||
- op: replace
|
|
||||||
path: /spec/observabilityAddonSpec/interval
|
|
||||||
value: 60
|
|
||||||
- op: add
|
|
||||||
path: /spec/advanced
|
|
||||||
value:
|
|
||||||
alertmanager:
|
|
||||||
replicas: 1
|
|
||||||
grafana:
|
|
||||||
replicas: 1
|
|
||||||
observatoriumAPI:
|
|
||||||
replicas: 1
|
|
||||||
query:
|
|
||||||
replicas: 1
|
|
||||||
queryFrontend:
|
|
||||||
replicas: 1
|
|
||||||
queryFrontendMemcached:
|
|
||||||
replicas: 1
|
|
||||||
rbacQueryProxy:
|
|
||||||
replicas: 1
|
|
||||||
receive:
|
|
||||||
replicas: 1
|
|
||||||
target:
|
|
||||||
kind: MultiClusterObservability
|
|
||||||
name: observability
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
resources:
|
|
||||||
- local-home.yaml
|
|
||||||
- local-hub.yaml
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
apiVersion: cluster.open-cluster-management.io/v1
|
|
||||||
kind: ManagedCluster
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
open-cluster-management/created-via: other
|
|
||||||
labels:
|
|
||||||
cloud: Other
|
|
||||||
cluster.open-cluster-management.io/clusterset: dev
|
|
||||||
gitops: local.home
|
|
||||||
color: "0066CC"
|
|
||||||
name: home
|
|
||||||
vendor: OpenShift
|
|
||||||
name: home
|
|
||||||
spec:
|
|
||||||
hubAcceptsClient: true
|
|
||||||
leaseDurationSeconds: 60
|
|
||||||
managedClusterClientConfigs:
|
|
||||||
- url: https://api.home.ocplab.com:6443
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
apiVersion: cluster.open-cluster-management.io/v1
|
|
||||||
kind: ManagedCluster
|
|
||||||
metadata:
|
|
||||||
annotations:
|
|
||||||
open-cluster-management/created-via: other
|
|
||||||
labels:
|
|
||||||
cloud: Other
|
|
||||||
cluster.open-cluster-management.io/clusterset: default
|
|
||||||
gitops: local.hub
|
|
||||||
color: "3E8635"
|
|
||||||
local-cluster: "true"
|
|
||||||
name: local-cluster
|
|
||||||
velero.io/exclude-from-backup: "true"
|
|
||||||
vendor: OpenShift
|
|
||||||
name: local-cluster
|
|
||||||
spec:
|
|
||||||
hubAcceptsClient: true
|
|
||||||
leaseDurationSeconds: 60
|
|
||||||
managedClusterClientConfigs:
|
|
||||||
- url: https://api.hub.ocplab.com:6443
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
resources:
|
|
||||||
- policy-cert-expiration.yaml
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
apiVersion: policy.open-cluster-management.io/v1
|
|
||||||
kind: Policy
|
|
||||||
metadata:
|
|
||||||
name: certificate-expiration
|
|
||||||
annotations:
|
|
||||||
policy.open-cluster-management.io/categories: SC System and Communications Protection
|
|
||||||
policy.open-cluster-management.io/standards: NIST SP 800-53
|
|
||||||
policy.open-cluster-management.io/controls: SC-8 Transmission Confidentiality and Integrity
|
|
||||||
spec:
|
|
||||||
disabled: false
|
|
||||||
remediationAction: inform
|
|
||||||
policy-templates:
|
|
||||||
- objectDefinition:
|
|
||||||
apiVersion: policy.open-cluster-management.io/v1
|
|
||||||
kind: CertificatePolicy
|
|
||||||
metadata:
|
|
||||||
name: policy-certificate
|
|
||||||
spec:
|
|
||||||
namespaceSelector:
|
|
||||||
include:
|
|
||||||
- default
|
|
||||||
exclude:
|
|
||||||
- kube-*
|
|
||||||
remediationAction: inform
|
|
||||||
severity: low
|
|
||||||
minimumDuration: 300h
|
|
||||||
---
|
|
||||||
apiVersion: apps.open-cluster-management.io/v1
|
|
||||||
kind: PlacementRule
|
|
||||||
metadata:
|
|
||||||
name: certificate-expiration-placement
|
|
||||||
spec:
|
|
||||||
clusterSelector:
|
|
||||||
matchExpressions: []
|
|
||||||
clusterConditions:
|
|
||||||
- status: "True"
|
|
||||||
type: ManagedClusterConditionAvailable
|
|
||||||
---
|
|
||||||
apiVersion: policy.open-cluster-management.io/v1
|
|
||||||
kind: PlacementBinding
|
|
||||||
metadata:
|
|
||||||
name: certificate-expiration-placement
|
|
||||||
placementRef:
|
|
||||||
name: certificate-expiration-placement
|
|
||||||
apiGroup: apps.open-cluster-management.io
|
|
||||||
kind: PlacementRule
|
|
||||||
subjects:
|
|
||||||
- name: certificate-expiration
|
|
||||||
apiGroup: policy.open-cluster-management.io
|
|
||||||
kind: Policy
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
resources:
|
|
||||||
- scan-nist-800-53-policy.yaml
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
apiVersion: policy.open-cluster-management.io/v1
|
|
||||||
kind: Policy
|
|
||||||
metadata:
|
|
||||||
name: scan-nist-800-53
|
|
||||||
annotations:
|
|
||||||
policy.open-cluster-management.io/standards: NIST-CSF
|
|
||||||
policy.open-cluster-management.io/categories: PR.IP Information Protection Processes and Procedures
|
|
||||||
policy.open-cluster-management.io/controls: PR.IP-1 Baseline Configuration
|
|
||||||
spec:
|
|
||||||
remediationAction: enforce
|
|
||||||
disabled: false
|
|
||||||
policy-templates:
|
|
||||||
- objectDefinition:
|
|
||||||
apiVersion: policy.open-cluster-management.io/v1
|
|
||||||
kind: ConfigurationPolicy
|
|
||||||
metadata:
|
|
||||||
name: scan-nist-800-53
|
|
||||||
spec:
|
|
||||||
remediationAction: inform
|
|
||||||
severity: high
|
|
||||||
object-templates:
|
|
||||||
- complianceType: mustnothave
|
|
||||||
objectDefinition:
|
|
||||||
apiVersion: compliance.openshift.io/v1alpha1
|
|
||||||
kind: ComplianceCheckResult
|
|
||||||
metadata:
|
|
||||||
namespace: openshift-compliance
|
|
||||||
labels:
|
|
||||||
compliance.openshift.io/check-status: FAIL
|
|
||||||
compliance.openshift.io/suite: cis-compliance
|
|
||||||
---
|
|
||||||
apiVersion: policy.open-cluster-management.io/v1
|
|
||||||
kind: PlacementBinding
|
|
||||||
metadata:
|
|
||||||
name: binding-scan-nist-800-53
|
|
||||||
placementRef:
|
|
||||||
name: placement-scan-nist-800-53
|
|
||||||
kind: PlacementRule
|
|
||||||
apiGroup: apps.open-cluster-management.io
|
|
||||||
subjects:
|
|
||||||
- name: scan-nist-800-53
|
|
||||||
kind: Policy
|
|
||||||
apiGroup: policy.open-cluster-management.io
|
|
||||||
---
|
|
||||||
apiVersion: apps.open-cluster-management.io/v1
|
|
||||||
kind: PlacementRule
|
|
||||||
metadata:
|
|
||||||
name: placement-scan-nist-800-53
|
|
||||||
spec:
|
|
||||||
clusterConditions:
|
|
||||||
- status: 'True'
|
|
||||||
type: ManagedClusterConditionAvailable
|
|
||||||
clusterSelector:
|
|
||||||
matchExpressions:
|
|
||||||
- {key: vendor, operator: In, values: ["OpenShift"]}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user