1 - Angular Documentation

A comprehensive guide to understanding and working with the Angular framework.

Angular Documentation

Welcome to the Angular documentation. This guide will help you understand and work with Angular framework.

Table of Contents

Overview

Angular is a platform and framework for building single-page client applications using HTML and TypeScript. Angular is written in TypeScript. It implements core and optional functionality as a set of TypeScript libraries that you import into your applications.

Overview (5 minutes)

What is Angular?

A front-end framework developed by Google for building dynamic web applications (SPA - Single Page Application).

Key Difference

Angular (2+) is a complete rewrite and fundamentally different from AngularJS (1.x). It’s built with TypeScript and offers improved performance, better dependency injection, and more intuitive component architecture.

Basic Setup

  • Node.js installation required
  • npm (Node Package Manager)
  • Angular CLI installation: npm install -g @angular/cli
  • Create new project: ng new

Evaluation Question

“What’s an SPA? Can anyone explain?”

Architecture

Angular Architecture

Key Features

  • Component-Based Architecture: Build encapsulated components that manage their own templates and logic
  • Modern Tools: Use modern tools for development, testing, and deployment
  • Performance: Fast rendering and deep optimization capabilities
  • Full Development Story: Everything you need to build complex applications

Prerequisites

  • Node.js (version 16.x or higher)
  • npm (Node Package Manager)
  • Basic knowledge of HTML, CSS, and JavaScript/TypeScript

Getting Help

For detailed information about each topic, please follow the links in the Table of Contents.

1.1 - Getting Started

Overview about Angular

Getting Started with Angular

Overview (5 minutes)

What is Angular?

Angular is a powerful front-end framework developed by Google for building dynamic web applications, specifically Single Page Applications (SPAs). It provides a comprehensive solution for:

  • Building scalable web applications
  • Creating reusable UI components
  • Managing application state
  • Handling routing and navigation
  • Form handling and validation

Key Differences: Angular vs AngularJS

Angular (2+) represents a complete reimagining of the original AngularJS framework:

FeatureAngular (2+)AngularJS (1.x)
LanguageTypeScriptJavaScript
ArchitectureComponent-basedMVC
Mobile SupportYesLimited
PerformanceImprovedBasic
Learning CurveModerateSteep

Basic Setup Requirements

  1. Node.js

    • Download from nodejs.org
    • Recommended version: 16.x or higher
    • Includes npm (Node Package Manager)
  2. Angular CLI

    npm install -g @angular/cli
    
  3. Create New Project

    ng new my-app
    cd my-app
    ng serve
    

Playground

View the Playground

Understanding SPAs

A Single Page Application (SPA) is a web application that:

  • Loads a single HTML page
  • Dynamically updates content without full page reloads
  • Provides a more fluid user experience
  • Reduces server load by only requesting data, not entire pages

Benefits of SPAs:

  • Faster user experience after initial load
  • Reduced server load
  • Better caching capabilities
  • More app-like feel

Common Questions

Q: “What’s an SPA? Can anyone explain?” A: An SPA is a web application that operates within a single page, dynamically rewriting the current page rather than loading entire new pages from the server.

Next Steps

1.2 - Components

What is component and how does it work

Components (10 minutes)

Components: The Building Blocks

Components are the fundamental building blocks of Angular applications. Each component consists of:

  • A TypeScript class with the @Component decorator
  • An HTML template defining the UI
  • CSS styles specific to the component

Creating a Component

Checking on Playround: ng-002 | Basic Component

Using Angular CLI:

ng generate component hello-world
# or shorter version
ng g c hello-world

This creates:

hello-world/
├── hello-world.component.ts
├── hello-world.component.html
├── hello-world.component.css
└── hello-world.component.spec.ts

Basic Component Example

// hello-world.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world',
  template: `
    <h1>{{ greeting }}</h1>
    <button (click)="changeGreeting()">Change Greeting</button>
  `,
  styles: [`
    h1 { color: blue; }
  `]
})
export class HelloWorldComponent {
  greeting = 'Hello, World!';

  changeGreeting() {
    this.greeting = 'Hello, Angular!';
  }
}

Component Interaction

Checking on Playround: ng-002 | Parent Component

Parent to Child (@Input)

Use @Input decorator to pass data from parent to child components:

// child.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <h2>Hello, {{name}}!</h2>
    <button (click)="onClick()">Click me</button>
  `
})
export class ChildComponent {
  @Input() name: string = '';  // Receive name from parent

  onClick() {
    this.buttonClicked.emit(`Button clicked by ${this.name}`);
  }
}

// parent.component.ts
@Component({
  selector: 'app-parent',
  template: `
    <h1>Parent Component</h1>
    <app-child 
      [name]="parentName"
      (buttonClicked)="handleClick($event)">
    </app-child>
  `
})
export class ParentComponent {
  parentName = 'John';  // Data to send to child

  handleClick(message: string) {
    console.log(message);  // Logs: "Button clicked by John"
  }
}

Child to Parent (@Output)

Use @Output decorator with EventEmitter to send data from child to parent:

// child.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-child',
  template: `
    <h2>Hello, {{name}}!</h2>
    <button (click)="onClick()">Click me</button>
  `
})
export class ChildComponent {
  @Input() name: string = '';
  @Output() buttonClicked = new EventEmitter<string>();

  onClick() {
    this.buttonClicked.emit(`Button clicked by ${this.name}`);
  }
}

Complete Example

Here’s a practical example combining both @Input and @Output:

// message.interface.ts
interface Message {
  text: string;
  sender: string;
  timestamp: Date;
}

// message.component.ts
@Component({
  selector: 'app-message',
  template: `
    <div class="message">
      <h3>From: {{name}}</h3>
      <input [(ngModel)]="messageText">
      <button (click)="sendMessage()">Send</button>
    </div>
  `
})
export class MessageComponent {
  @Input() name: string = '';
  @Output() messageSent = new EventEmitter<Message>();
  
  messageText = '';

  sendMessage() {
    this.messageSent.emit({
      text: this.messageText,
      sender: this.name,
      timestamp: new Date()
    });
    this.messageText = '';
  }
}

// chat.component.ts
@Component({
  selector: 'app-chat',
  template: `
    <app-message
      [name]="userName"
      (messageSent)="handleMessage($event)">
    </app-message>
    <div class="message-list">
      <div *ngFor="let msg of messages">
        {{msg.sender}}: {{msg.text}}
        <small>{{msg.timestamp | date:'short'}}</small>
      </div>
    </div>
  `
})
export class ChatComponent {
  userName = 'John';
  messages: Message[] = [];

  handleMessage(message: Message) {
    this.messages.push(message);
  }
}

Best Practices

  1. Use meaningful names for @Input and @Output properties
  2. Keep component communication simple and predictable
  3. Document complex interactions
  4. Use TypeScript interfaces for complex data structures
  5. Handle edge cases and errors in component communication
  6. Consider using services for complex state management between components

1.3 - Data Binding

Basic data binding

Data Binding in Angular

Types of Data Binding

Angular provides several ways to bind data between your component’s TypeScript code and the HTML template.

Playground

1. One-way Binding

Data flows in one direction: from the component to the view (HTML).

Interpolation {{ }}

Displays component data in the view:

// component.ts
export class GreetingComponent {
  name = 'John';
}
<!-- template.html -->
<h1>Hello, {{name}}!</h1>

Property Binding [ ]

Binds a component property to an element property:

// component.ts
export class ButtonComponent {
  isDisabled = true;
  imageUrl = 'path/to/image.jpg';
}
<!-- template.html -->
<button [disabled]="isDisabled">Click me</button>
<img [src]="imageUrl" [alt]="'Profile image'">

2. Two-way Binding [( )]

Synchronizes data in both directions between the component and view.

Using ngModel

First, import FormsModule in your module:

// app.module.ts
import { FormsModule } from '@angular/forms';

@NgModule({
  imports: [
    BrowserModule,
    FormsModule  // Add this
  ],
  // ...
})
export class AppModule { }

Then use [(ngModel)] in your component:

// component.ts
export class NameComponent {
  name = '';
}
<!-- template.html -->
<input [(ngModel)]="name">
<p>Hello, {{name}}!</p>

Complete Example

Here’s a working example combining different types of binding:

// name-editor.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-name-editor',
  template: `
    <div>
      <label>Name: </label>
      <!-- Two-way binding -->
      <input [(ngModel)]="name">
      
      <!-- One-way binding with interpolation -->
      <p>Hello, {{name}}!</p>
      
      <!-- Property binding -->
      <button [disabled]="!name">Clear</button>
      
      <!-- Event binding -->
      <button (click)="resetName()">Reset</button>
    </div>
  `
})
export class NameEditorComponent {
  name = '';

  resetName() {
    this.name = '';
  }
}

Evaluation Question

Q: “How do you change an input value without ngModel?”

A: You can use a combination of property binding and event binding (also known as “banana in a box” syntax):

// component.ts
export class ManualBindingComponent {
  name = '';

  onNameChange(event: any) {
    this.name = event.target.value;
  }
}
<!-- template.html -->
<input [value]="name" (input)="onNameChange($event)">
<p>Hello, {{name}}!</p>

This approach:

  1. Uses [value] to bind the component property to the input
  2. Uses (input) event to update the component property when the user types
  3. Gives you more control over the input handling
  4. Doesn’t require FormsModule

Best Practices

  1. Use interpolation {{ }} for text content
  2. Use property binding [ ] for element properties
  3. Use [(ngModel)] for form inputs when two-way binding is needed
  4. Consider manual binding for more control or when FormsModule isn’t available
  5. Always validate and sanitize user input when using two-way binding

1.4 - Modules

Basic modules, recommendation

Components (10 minutes)

Modules: Code Organization

Modules in Angular help organize related code into cohesive blocks of functionality. They are decorated with @NgModule.

Module Structure

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { HelloWorldComponent } from './hello-world/hello-world.component';

@NgModule({
  declarations: [
    AppComponent,
    HelloWorldComponent    // Components must be declared in a module
  ],
  imports: [
    BrowserModule         // Other modules we want to use
  ],
  providers: [],          // Services for dependency injection
  bootstrap: [AppComponent] // Root component to start with
})
export class AppModule { }

Key Module Concepts

  1. Declarations: List of components, directives, and pipes that belong to this module
  2. Imports: Other modules that this module needs
  3. Providers: Services that will be available to the entire application
  4. Bootstrap: The main application view (root component)

Feature Modules

For better organization, you can create feature modules:

ng generate module feature-name

Example structure:

@NgModule({
  declarations: [FeatureComponent],
  imports: [
    CommonModule,
    FeatureRoutingModule
  ],
  exports: [FeatureComponent]  // Make components available to other modules
})
export class FeatureModule { }

Evaluation Question

Q: “To add a new page, do you create a component or a module? Why?”

A: The answer depends on your needs:

  • Create a Component if you’re adding a single new page/view
  • Create a Module if you’re adding a feature with multiple related components, services, and routes

Best practices:

  • Components for individual pages/features
  • Modules for grouping related functionality
  • Feature modules for lazy loading and better organization

Common Patterns

  1. Shared Module: For commonly used components, directives, and pipes
  2. Core Module: For singleton services and single-load components
  3. Feature Modules: For distinct features of your application
  4. Routing Modules: For managing navigation between pages

1.5 - Dependency Injection

Basic Dependency Injection, singleton pattern and reuseable

Dependency Injection (DI) in Angular

What is Dependency Injection?

Dependency Injection (DI) is a design pattern where classes receive their dependencies from an external source rather than creating them internally. In Angular, the DI system provides and manages dependencies across your application.

Basic Service Example

Here’s a simple service that manages a list of Fresher names:

// fresher.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'  // Makes this a singleton service
})
export class FresherService {
  private freshers: string[] = [
    'John Doe',
    'Jane Smith',
    'Mike Johnson'
  ];

  getFreshers(): string[] {
    return this.freshers;
  }

  addFresher(name: string) {
    this.freshers.push(name);
  }
}

Using the Service in Components

// fresher-list.component.ts
import { Component, OnInit } from '@angular/core';
import { FresherService } from './fresher.service';

@Component({
  selector: 'app-fresher-list',
  template: `
    <h2>Fresher List</h2>
    <ul>
      <li *ngFor="let fresher of freshers">
        {{ fresher }}
      </li>
    </ul>
    <button (click)="addNewFresher()">Add Fresher</button>
  `
})
export class FresherListComponent implements OnInit {
  freshers: string[] = [];

  constructor(private fresherService: FresherService) {}

  ngOnInit() {
    this.freshers = this.fresherService.getFreshers();
  }

  addNewFresher() {
    this.fresherService.addFresher('New Fresher');
    this.freshers = this.fresherService.getFreshers();
  }
}

Service with HTTP Example

Here’s a more realistic example using HttpClient:

// fresher.interface.ts
interface Fresher {
  id: number;
  name: string;
  email: string;
}

// fresher.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({
  providedIn: 'root'
})
export class FresherService {
  private apiUrl = 'api/freshers';

  constructor(private http: HttpClient) {}

  getFreshers(): Observable<Fresher[]> {
    return this.http.get<Fresher[]>(this.apiUrl);
  }

  addFresher(fresher: Fresher): Observable<Fresher> {
    return this.http.post<Fresher>(this.apiUrl, fresher);
  }
}

DI Providers

There are different ways to provide services in Angular:

  1. Root-level Provider (Singleton):
@Injectable({
  providedIn: 'root'
})
  1. Module-level Provider:
@NgModule({
  providers: [FresherService]
})
  1. Component-level Provider:
@Component({
  providers: [FresherService]  // New instance for this component
})

Best Practices

  1. Use providedIn: ‘root’ for singleton services
@Injectable({
  providedIn: 'root'
})
  1. Implement OnDestroy for cleanup:
export class MyService implements OnDestroy {
  ngOnDestroy() {
    // Cleanup code
  }
}
  1. Use Interfaces for better type safety:
interface ServiceConfig {
  apiUrl: string;
  timeout: number;
}

@Injectable({providedIn: 'root'})
class MyService {
  constructor(@Inject('CONFIG') private config: ServiceConfig) {}
}
  1. Lazy Loading with feature modules:
@Injectable({
  providedIn: 'any'  // New instance per lazy-loaded module
})

Common Use Cases

  1. Data Services: Managing application data
@Injectable({providedIn: 'root'})
export class DataService {
  private data: any[] = [];
  
  getData() { return this.data; }
  addData(item: any) { this.data.push(item); }
}
  1. State Management: Managing application state
@Injectable({providedIn: 'root'})
export class StateService {
  private state = new BehaviorSubject<any>(initialState);
  state$ = this.state.asObservable();
  
  updateState(newState: any) {
    this.state.next(newState);
  }
}
  1. Utility Services: Shared functionality
@Injectable({providedIn: 'root'})
export class UtilityService {
  formatDate(date: Date): string {
    return date.toLocaleDateString();
  }
  
  generateId(): string {
    return Math.random().toString(36).substr(2, 9);
  }
}

Testing with DI

describe('FresherComponent', () => {
  let component: FresherComponent;
  let service: FresherService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [FresherComponent],
      providers: [FresherService]
    });

    component = TestBed.createComponent(FresherComponent).componentInstance;
    service = TestBed.inject(FresherService);
  });

  it('should load freshers', () => {
    const mockFreshers = ['John', 'Jane'];
    spyOn(service, 'getFreshers').and.returnValue(mockFreshers);
    
    component.ngOnInit();
    expect(component.freshers).toEqual(mockFreshers);
  });
});

1.6 - Forms

Basic form data management

Forms in Angular (10 minutes)

Reactive Forms

Reactive Forms provide a model-driven approach to handling form inputs and validation. They are more robust, scalable, and testable than template-driven forms.

Setup

First, import ReactiveFormsModule in your module:

// app.module.ts
import { ReactiveFormsModule } from '@angular/forms';

@NgModule({
  imports: [
    BrowserModule,
    ReactiveFormsModule  // Add this
  ],
  // ...
})
export class AppModule { }

Basic Example

Here’s a simple form with a “Name” input that logs to console on submit:

// name-form.component.ts
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';

@Component({
  selector: 'app-name-form',
  template: `
    <form [formGroup]="form" (ngSubmit)="onSubmit()">
      <div>
        <label for="name">Name:</label>
        <input id="name" type="text" formControlName="name">
      </div>
      <button type="submit">Submit</button>
    </form>
  `
})
export class NameFormComponent {
  form = new FormGroup({
    name: new FormControl('')  // Initialize with empty string
  });

  onSubmit() {
    console.log(this.form.value);  // Logs: { name: 'whatever user typed' }
  }
}

Comparison with Template-driven Forms

Reactive Forms (FormGroup/FormControl)

  • Model-driven approach
  • More scalable for complex forms
  • Better for form validation
  • Easier to test
  • Synchronous data flow
  • Better type safety

Template-driven Forms (ngModel)

  • Simpler for basic forms
  • Similar to AngularJS
  • Asynchronous data flow
  • More magical (less explicit)

Adding Form Controls

To add more fields, simply add new FormControl instances to your FormGroup:

form = new FormGroup({
  name: new FormControl(''),
  email: new FormControl('')  // Adding email field
});

Corresponding template:

<form [formGroup]="form" (ngSubmit)="onSubmit()">
  <div>
    <label for="name">Name:</label>
    <input id="name" type="text" formControlName="name">
  </div>
  <div>
    <label for="email">Email:</label>
    <input id="email" type="email" formControlName="email">
  </div>
  <button type="submit">Submit</button>
</form>

Form Validation

You can add validators to your form controls:

import { Validators } from '@angular/forms';

form = new FormGroup({
  name: new FormControl('', Validators.required),
  email: new FormControl('', [
    Validators.required,
    Validators.email
  ])
});

Check validation status:

<div *ngIf="form.get('email')?.errors?.['required']">
  Email is required
</div>
<div *ngIf="form.get('email')?.errors?.['email']">
  Please enter a valid email
</div>

Evaluation Question

Q: “How do you add an ‘Email’ input to this form?”

A: To add an email input:

  1. Add the FormControl to your FormGroup:
form = new FormGroup({
  name: new FormControl(''),
  email: new FormControl('')  // Add this line
});
  1. Add the input to your template:
<div>
  <label for="email">Email:</label>
  <input id="email" type="email" formControlName="email">
</div>
  1. Optional: Add validation:
email: new FormControl('', [
  Validators.required,
  Validators.email
])

Best Practices

  1. Always use Reactive Forms for complex forms
  2. Group related fields using nested FormGroups
  3. Add proper validation with error messages
  4. Use typed forms (Angular 14+) for better type safety
  5. Handle form submission with proper error handling
  6. Use form builders for cleaner code:
constructor(private fb: FormBuilder) {
  this.form = this.fb.group({
    name: [''],
    email: ['']
  });
}

1.7 - Routing

Basic Routing

Angular Routing

Basic Routing Concepts

Angular Router enables navigation between views without page reloads, creating a smoother user experience.

Setup

  1. Configure routes in a routing module:
// app-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { FormPageComponent } from './form-page/form-page.component';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'form', component: FormPageComponent },
  { path: '**', redirectTo: '' }  // Wildcard route for 404
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }
  1. Add router outlet to your main app component:
<!-- app.component.html -->
<nav>
  <a routerLink="/">Home</a>
  <a routerLink="/form">Form Page</a>
</nav>

<router-outlet></router-outlet>

Example: Home and Form Page Navigation

Components Setup

// home.component.ts
@Component({
  selector: 'app-home',
  template: '<h1>Welcome Home!</h1>'
})
export class HomeComponent { }

// form-page.component.ts
@Component({
  selector: 'app-form-page',
  template: '<h1>Form Page</h1>'
})
export class FormPageComponent { }
  1. Using RouterLink directive:
<a routerLink="/form">Go to Form</a>
  1. Programmatic navigation:
import { Router } from '@angular/router';

export class NavComponent {
  constructor(private router: Router) {}

  goToForm() {
    this.router.navigate(['/form']);
  }
}

Running Code on Route Changes

To execute code on every route change, use Router events:

// app.component.ts
import { Component } from '@angular/core';
import { Router, NavigationEnd } from '@angular/router';
import { filter } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>'
})
export class AppComponent {
  constructor(private router: Router) {
    // Listen to route changes
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd)
    ).subscribe((event: NavigationEnd) => {
      console.log('Route changed to:', event.url);
      // Your code here
    });
  }
}

Using Route Guards

For more control over navigation:

// auth.guard.ts
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';

@Injectable({
  providedIn: 'root'
})
export class AuthGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(): boolean {
    // Your logic here
    return true;
  }
}

Apply guard to routes:

const routes: Routes = [
  { 
    path: 'form', 
    component: FormPageComponent,
    canActivate: [AuthGuard]
  }
];

Evaluation Question

Q: “How do you make a service run on every page change?”

A: There are several ways to run a service on page changes:

  1. Using Router Events in a Service:
@Injectable({
  providedIn: 'root'
})
export class RouteService {
  constructor(private router: Router) {
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd)
    ).subscribe(() => {
      this.onRouteChange();
    });
  }

  private onRouteChange() {
    // Your code here
    console.log('Route changed!');
  }
}
  1. Using Guards:
@Injectable({
  providedIn: 'root'
})
export class RouteGuard implements CanActivate {
  constructor(private myService: MyService) {}

  canActivate(): boolean {
    this.myService.doSomething();
    return true;
  }
}

Best Practices

  1. Always include a default route
  2. Handle 404 cases with a wildcard route
  3. Use route parameters for dynamic content
  4. Implement lazy loading for better performance
  5. Add route guards for protected routes
  6. Use route resolvers for data pre-fetching
  7. Consider using child routes for nested views

1.8 -

2 - Node.js Documentation

A comprehensive guide to understanding and working with Node.js.

Node.js Documentation

Welcome to the Node.js documentation. This guide will help you understand and work with Node.js.

Table of Contents

Basic Concepts

ConceptDescription
Node.jsJavaScript runtime built on Chrome’s V8 JavaScript engine
Event-drivenUses non-blocking I/O model that makes it lightweight and efficient
NPMNode Package Manager for installing and managing dependencies
package.jsonConfiguration file that contains metadata about the project
ModulesReusable blocks of code that can be imported/exported

Core Modules

ModuleDescription
fsFile system operations
httpHTTP server and client functionality
pathUtilities for working with file and directory paths
osOperating system-related utility methods
eventsFor handling and emitting events
utilUtility functions
streamFor working with streaming data
cryptoCryptographic functionality

NPM Commands

CommandDescription
npm initInitialize a new Node.js project
npm install <package>Install a package
npm install -g <package>Install a package globally
npm install --save-dev <package>Install as a development dependency
npm uninstall <package>Uninstall a package
npm updateUpdate packages
npm listList installed packages
npm run <script>Run a script defined in package.json

File System Operations

Package Manager

2.1 - NestJS

NestJS is a framework for building efficient, scalable Node.js server-side applications. It uses modern JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Programming), FP (Functional Programming), and FRP (Functional Reactive Programming).

3 - Git & Common Git Providers

A comprehensive guide to understanding and working with Git version control system.

Git Documentation

Welcome to the Git documentation. This guide will help you understand and work with Git version control system.

Table of Contents

Basic Commands

CommandDescription
git initInitialize a new Git repository
git clone <url>Clone a repository from remote source
git add <file>Add file(s) to staging area
git add .Add all modified files to staging area
git commit -m "message"Commit staged changes with a message
git statusShow working tree status
git logShow commit history
git diffShow changes between commits, commit and working tree, etc.

Branching and Merging

CommandDescription
git branchList all local branches
git branch -aList all branches (local and remote)
git branch <branch-name>Create a new branch
git checkout <branch-name>Switch to specified branch
git checkout -b <branch-name>Create and switch to a new branch
git merge <branch-name>Merge specified branch into current branch
git branch -d <branch-name>Delete a branch

Remote Repositories

CommandDescription
git remote -vList all remote repositories
git remote add <name> <url>Add a new remote repository
git push <remote> <branch>Push branch to remote repository
git pull <remote> <branch>Pull changes from remote repository
git fetch <remote>Download objects and refs from remote

Advanced Operations

CommandDescription
git stashStash changes in working directory
git stash popApply stashed changes and remove from stash
git reset --hard <commit>Reset working directory to specified commit
git rebase <branch>Reapply commits on top of another base
git cherry-pick <commit>Apply changes from specific commit
git tag <name>Create a tag

Configuration

CommandDescription
git config --global user.name "Name"Set global username
git config --global user.email "email"Set global email
git config --listList all configuration
git config --global alias.<alias-name> <git-command>Create command alias

Common Workflows

Feature Branch Workflow

  1. Create a feature branch: git checkout -b feature-name
  2. Make changes and commit: git add . and git commit -m "message"
  3. Push to remote: git push origin feature-name
  4. Create pull request (via web interface)
  5. After review, merge to main branch

Fixing Mistakes

  • Amend last commit: git commit --amend
  • Undo last commit (keeping changes): git reset HEAD~1
  • Discard all local changes: git reset --hard
  • Discard changes to a file: git checkout -- <file>

3.1 - GitLab

4 - Docker Cheat Sheet

Hướng dẫn sử dụng Docker và các lệnh thông dụng

Docker Cheat Sheet

Các lệnh cơ bản

Quản lý Images

Cài đặt Docker

Ubuntu

4.1 - Docker Cheat Sheet

Hướng dẫn sử dụng Docker và các lệnh thông dụng

Docker Cheat Sheet

Các lệnh cơ bản

Quản lý Images

Cài đặt Docker

Ubuntu

4.2 - Docker Architecture

Docker uses a client-server architecture with several key components working together to build, run, and distribute containerized applications.

Architecture Overview

flowchart TD
    Client[Docker CLI] -->|commands| Daemon[Docker Daemon]
    Daemon -->|manages| Images[Images]
    Daemon -->|manages| Containers[Containers]
    Daemon -->|manages| Networks[Networks]
    Daemon -->|manages| Volumes[Volumes]
    Images -->|create| Containers
    Registry[Registry] <-->|push/pull| Images
    
    style Client fill:#f9d77e,stroke:#333,stroke-width:2px
    style Daemon fill:#78a9ff,stroke:#333,stroke-width:2px
    style Images fill:#ffe6cc,stroke:#333,stroke-width:2px
    style Containers fill:#d5e8d4,stroke:#333,stroke-width:2px
    style Networks fill:#e1d5e7,stroke:#333,stroke-width:2px
    style Volumes fill:#fff2cc,stroke:#333,stroke-width:2px
    style Registry fill:#f8cecc,stroke:#333,stroke-width:2px

This simplified overview shows the core components of Docker’s architecture:

  • Docker CLI: The command-line interface users interact with
  • Docker Daemon: The background service managing all Docker objects
  • Images: Read-only templates used to create containers
  • Containers: Running instances of Docker images
  • Networks: Allow containers to communicate with each other
  • Volumes: Persistent data storage for containers
  • Registry: Stores and distributes Docker images

Architecture Diagram

graph TD
    subgraph "Docker Host"
        A[Docker Daemon] --- B[Container Runtime]
        A --- C[Images]
        A --- D[Volumes]
        A --- E[Networks]
        
        B --- F[Container 1]
        B --- G[Container 2]
        B --- H[Container 3]
        
        F --- I[App Process]
        G --- J[App Process]
        H --- K[App Process]
    end
    
    L[Docker Client] --- A
    A --- M[Registry]
    
    classDef container fill:#66aa66,stroke:#333,stroke-width:2px;
    classDef daemon fill:#4477aa,stroke:#333,stroke-width:2px;
    classDef client fill:#aa6644,stroke:#333,stroke-width:2px;
    classDef registry fill:#aa66aa,stroke:#333,stroke-width:2px;
    
    class A daemon;
    class F,G,H container;
    class L client;
    class M registry;

Key Components

Docker Client

The Docker client (docker) is the primary way users interact with Docker. When you use commands like docker run, the client sends these commands to the Docker daemon, which carries them out.

Docker Daemon

The Docker daemon (dockerd) listens for Docker API requests and manages Docker objects such as images, containers, networks, and volumes. A daemon can also communicate with other daemons to manage Docker services.

Container Runtime

The container runtime is the component that actually runs containers. Docker uses containerd as its container runtime, which handles lower-level container execution.

Images

A Docker image is a read-only template with instructions for creating a Docker container. Often, an image is based on another image, with some additional customization.

Containers

A container is a runnable instance of an image. You can create, start, stop, move, or delete a container using the Docker API or CLI.

Docker Registry

A Docker registry stores Docker images. Docker Hub is a public registry that anyone can use, and Docker is configured to look for images on Docker Hub by default. You can also run your own private registry.

Volumes and Networks

Docker provides persistent data storage through volumes and networking capabilities through network drivers.

5 - PostgreSQL

PostgreSQL is a powerful, open-source object-relational database system.

6 - Development

How to contribute to the Kubernetes project

6.1 - Development Container

Using Development Containers for VDAT Documentation

Development Container for VDAT Docs

This documentation site supports development using VS Code Development Containers, which provides a consistent, isolated environment for editing and previewing the documentation.

Prerequisites

  1. Docker
  2. Visual Studio Code
  3. Remote - Containers extension for VS Code

Getting Started

  1. Clone the repository:

    git clone https://gitlab.com/vdat/docs.git
    cd docs
    
  2. Open the project in VS Code:

    code .
    
  3. When prompted, click “Reopen in Container” or use the command palette (F1) and select “Remote-Containers: Reopen in Container”.

  4. VS Code will build the dev container (this may take a few minutes the first time).

  5. Once the container is built and running, you can start the Hugo server:

    hugo server --bind 0.0.0.0
    
  6. Access the live preview at http://localhost:1313

Features

The development container includes:

  • Hugo (Extended Edition)
  • Node.js and NPM (for Docsy dependencies)
  • Git
  • Pandoc for document conversions
  • PlantUML and Graphviz for diagrams
  • VS Code extensions for Markdown, YAML, and Hugo
  • PostCSS and Autoprefixer for CSS processing

Common Tasks

Adding New Content

# Create a new page in a section
hugo new content/en/docs/section/page-name.md

Building the Site

# Development build with live reload
hugo server --bind 0.0.0.0

# Production build
hugo

Installing NPM Dependencies

npm install

Troubleshooting

If you encounter issues with the dev container:

  1. Rebuild the container using VS Code’s command palette: “Remote-Containers: Rebuild Container”
  2. Check Docker Desktop to ensure the container is running
  3. Verify port 1313 is forwarded correctly (check VS Code’s “Ports” tab in the Remote Explorer)

6.2 - OpenAPI Specification

OpenAPI Specification

7 - Go Programming

Resources, tutorials, and best practices for Go programming.

This section contains documentation related to Go programming language, including tutorials, best practices, and code examples.

Overview

Go (or Golang) is an open source programming language designed for building simple, fast, and reliable software. This section provides resources to help you learn and use Go effectively in your projects.

8 - Data Platform

VDAT’s comprehensive data platform for healthcare analytics, from collection to insights.

VDAT Data Platform

The VDAT Data Platform provides an end-to-end solution for healthcare data management, analytics, and insights generation. Our platform encompasses the full data lifecycle:

  1. Data Collection & Integration - Secure capture and standardization of healthcare data
  2. Data Visualization - Interactive dashboards and visual analytics tools
  3. Data Governance - Comprehensive frameworks for security, privacy, and compliance
  4. Machine Learning - Advanced algorithms for predictive modeling and insights
  5. Medical Imaging - Specialized tools for medical imaging data processing and analysis

This unified approach ensures seamless data flow while maintaining the highest standards of data quality, security, and accessibility for authorized healthcare stakeholders.

8.1 - Data Collection & Integration

8.2 - Data Integration

8.3 - Data Visualization & Analytics

Interactive dashboards and visual analytics tools for healthcare data insights.

Data Visualization

The VDAT data visualization capabilities enable healthcare professionals and researchers to transform complex health data into intuitive visual representations.

Features

  • Interactive Dashboards - Customizable views of key metrics and trends
  • Clinical Visualizations - Specialized visualizations for clinical data
  • Real-time Analytics - Live data streaming and visualization
  • Comparative Analysis - Tools for benchmarking and trend analysis
  • Custom Reporting - Configurable report generation for stakeholders

8.4 - Data Governance & Compliance

Comprehensive frameworks for security, privacy, and regulatory compliance.

Data Governance

VDAT’s data governance framework ensures that healthcare data is managed securely, ethically, and in compliance with relevant regulations throughout its lifecycle.

Components

  • Access Control - Role-based permission systems and authentication protocols
  • Data Privacy - De-identification and anonymization methodologies
  • Audit Trails - Comprehensive logging and monitoring of data access
  • Regulatory Compliance - Frameworks for HIPAA, GDPR, and other healthcare regulations
  • Data Quality Management - Procedures for ensuring accuracy and consistency
  • Metadata Management - Standardized data cataloging and documentation

8.5 - Statistical Learning Models

Advanced computational methods and algorithms for healthcare data analysis.

Statistical Learning Models

VDAT’s machine learning capabilities apply advanced computational techniques to extract meaningful patterns and predictions from healthcare data.

Methodologies

  • Supervised Learning - Classification and regression models for clinical prediction
  • Unsupervised Learning - Clustering and dimensionality reduction for pattern discovery
  • Deep Learning - Neural network architectures for complex healthcare data analysis
  • Natural Language Processing - Text analysis for clinical notes and medical literature
  • Time Series Analysis - Sequential data modeling for patient trajectories
  • Explainable AI - Transparent models with interpretable results for clinical decision support

8.6 - Medical Imaging

Specialized tools and methodologies for medical image acquisition, processing, and analysis.

Medical Imaging

VDAT provides comprehensive solutions for handling medical imaging data across various modalities, supporting both clinical and research applications.

Capabilities

  • Multi-modality Support - Compatible with DICOM, NIfTI, and other imaging formats
  • Image Processing - Advanced filtering, registration, and segmentation tools
  • AI-assisted Analysis - Automated detection and quantification algorithms
  • 3D Visualization - Interactive three-dimensional rendering of volumetric data
  • Annotation Tools - Collaborative labeling and region-of-interest marking
  • Integration with PACS - Seamless connection with existing clinical imaging systems

9 - Security & Compliance

Tài liệu về bảo mật và xác thực

Bảo mật và xác thực

Phần này bao gồm các tài liệu về bảo mật, xác thực và phân quyền trong hệ thống.

9.1 - Basic Security Concepts: Authentication

Fundamental security concepts and authentication methods

Overview

This document covers the basic security concepts and authentication methods used in web applications.

Authentication Methods

MethodDescriptionUse Cases
Basic AuthSimple username/password authentication sent in HTTP headersDevelopment environments, simple APIs
JWT TokenJSON Web Tokens for stateless authenticationModern web applications, microservices
OAuth2Authorization framework that enables third-party applications to obtain limited accessSocial logins, API authorization

Basic Authentication

Basic Authentication is a simple authentication scheme built into the HTTP protocol. The client sends HTTP requests with the Authorization header that contains the word Basic followed by a space and a base64-encoded string username:password.

9.1.1 - JSON Web Token (JWT)

Understanding JSON Web Tokens (JWT) for secure authentication and information exchange.

JSON Web Tokens (JWT) provide a compact, URL-safe means of representing claims securely between two parties. They are commonly used for authentication and authorization in web applications.

What is JWT?

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed.

JWTs can be:

  • Signed using a secret (with the HMAC algorithm) or a public/private key pair (RSA or ECDSA)
  • Encrypted to also provide secrecy between parties

JWT Structure

A JWT consists of three parts separated by dots (.):

xxxxx.yyyyy.zzzzz
  • Header (xxxxx): Contains token type and signing algorithm
  • Payload (yyyyy): Contains claims (user data and metadata)
  • Signature (zzzzz): Ensures the token hasn’t been altered

JWT Token Structure Visualization

graph LR
    A[JWT Token] --> B[Header]
    A --> C[Payload]
    A --> D[Signature]
    
    B --> B1[Base64Url Encoded]
    C --> C1[Base64Url Encoded]
    
    B1 --> E["{ 
        alg: 'HS256',
        typ: 'JWT' 
    }"]
    
    C1 --> F["{ 
        sub: '1234567890',
        name: 'John Doe',
        iat: 1516239022,
        exp: 1516242622
    }"]
    
    D --> G["HMACSHA256(
        base64UrlEncode(header) + '.' +
        base64UrlEncode(payload),
        secret)"]

How JWT Works

JWT authentication follows a simple flow:

  1. User logs in with credentials
  2. Server validates credentials and generates a JWT
  3. JWT is returned to the client
  4. Client stores the JWT (typically in local storage or a cookie)
  5. Client sends the JWT with subsequent requests
  6. Server validates the JWT signature and processes the request

JWT Authentication Flow

sequenceDiagram
    participant User
    participant Client
    participant Server
    
    User->>Client: Enter credentials
    Client->>Server: Authentication request
    Note right of Server: Validate credentials
    Server->>Server: Generate JWT with payload and signature
    Server->>Client: Return JWT
    Note left of Client: Store JWT
    
    loop For each protected request
        Client->>Server: Request with JWT in Authorization header
        Note right of Server: Validate JWT signature
        Note right of Server: Check expiration
        Server->>Client: Protected resource/response
    end

JWT Claims

Claims are statements about an entity (typically the user) and additional metadata. There are three types of claims:

  1. Registered Claims: Predefined claims providing a set of useful, interoperable claims

    • iss (issuer)
    • sub (subject)
    • aud (audience)
    • exp (expiration time)
    • nbf (not before)
    • iat (issued at)
    • jti (JWT ID)
  2. Public Claims: Custom claims defined by those using JWTs

  3. Private Claims: Custom claims created to share information between parties

JWT Implementation Example

Here’s a simplified example of generating and validating a JWT:

Server-side: Generating a JWT (Node.js)

const jwt = require('jsonwebtoken');

// User authentication function
function authenticate(username, password) {
  // Validate user credentials (simplified)
  if (isValidUser(username, password)) {
    // Create token payload
    const payload = {
      sub: getUserId(username),
      name: username,
      role: getUserRole(username),
      iat: Math.floor(Date.now() / 1000),
      exp: Math.floor(Date.now() / 1000) + (60 * 60) // 1 hour expiration
    };
    
    // Generate and sign token
    const token = jwt.sign(payload, process.env.JWT_SECRET);
    return token;
  }
  throw new Error('Authentication failed');
}

Server-side: Validating a JWT (Node.js)

const jwt = require('jsonwebtoken');

// Middleware to validate JWT
function verifyToken(req, res, next) {
  // Get auth header value
  const bearerHeader = req.headers['authorization'];
  
  if (bearerHeader) {
    // Extract token from "Bearer <token>"
    const token = bearerHeader.split(' ')[1];
    
    jwt.verify(token, process.env.JWT_SECRET, (err, decoded) => {
      if (err) {
        return res.status(403).json({ message: 'Invalid or expired token' });
      }
      
      // Add decoded user info to request object
      req.user = decoded;
      next();
    });
  } else {
    res.status(401).json({ message: 'Access denied. No token provided.' });
  }
}

JWT Storage Security Diagram

graph TD
    A[JWT Storage Options] --> B[Browser Storage]
    A --> C[HTTP Only Cookie]
    
    B --> D[localStorage]
    B --> E[sessionStorage]
    B --> F[Memory Variable]
    
    D --> G[Pros: Simple, Persists]
    D --> H[Cons: XSS Vulnerable]
    
    E --> I[Pros: Session-bound]
    E --> J[Cons: XSS Vulnerable]
    
    F --> K[Pros: Not accessible via XSS]
    F --> L[Cons: Lost on refresh]
    
    C --> M[Pros: XSS Protected, CSRF can be mitigated]
    C --> N[Cons: Server config required]
    
    style C fill:#c9e7f9
    style M fill:#c9f9d9

Best Practices for JWT

  1. Use HTTPS: Always transmit JWTs over HTTPS to prevent token theft through network eavesdropping

  2. Set Proper Expiration: Use short expiration times and implement token refresh

    graph LR
        A[Token Types] --> B[Access Token]
        A --> C[Refresh Token]
        B --> D[Short lived: 15min - 1hr]
        C --> E[Longer lived: days/weeks]
        B --> F[Frequent validation]
        C --> G[Stored securely server-side]
  3. Validate All Claims: Check issuer, audience, expiration, and all other relevant claims

  4. Keep Tokens Small: Include only necessary data in the payload to maintain performance

  5. Secure Storage: Store tokens securely, preferably in HttpOnly cookies for web applications

  6. Implement Token Revocation: Have a strategy for invalidating tokens when needed (logout, password change)

  7. Use Strong Keys: Use strong, randomly generated secrets for signing tokens

JWT vs Session Authentication

graph TB
    subgraph "JWT Authentication"
        A1[Client] -->|1. Login| B1[Server]
        B1 -->|2. JWT Token| A1
        A1 -->|3. Request with JWT| B1
        B1 -->|4. Validate JWT & Respond| A1
    end
    
    subgraph "Session Authentication"
        A2[Client] -->|1. Login| B2[Server]
        B2 -->|2. Session ID Cookie| A2
        A2 -->|3. Request with Cookie| B2
        B2 -->|4. Lookup Session & Respond| B2
    end
    
    C[Comparison]
    C --> D[JWT: Stateless, no session storage]
    C --> E[Session: Stateful, session storage required]
    C --> F[JWT: Larger request size]
    C --> G[Session: Smaller request size]
    C --> H[JWT: Decentralized validation possible]
    C --> I[Session: Centralized validation required]

Common JWT Security Vulnerabilities

  1. None Algorithm Attack: Ensure your JWT library rejects tokens with the “none” algorithm

  2. Algorithm Confusion: Ensure proper algorithm verification is implemented

  3. Missing Signature Validation: Always validate signatures, never trust just the presence of a token

  4. Weak Secrets: Use strong, random secrets or keys for token signing

  5. Token Sidejacking: Implement additional security measures to prevent token theft

Further Reading

9.1.2 - OAuth2

Tài liệu về OAuth2 và cách sử dụng trong hệ thống

OAuth2 và OpenID Connect

OAuth2 là một giao thức ủy quyền cho phép các ứng dụng bên thứ ba có thể truy cập tài nguyên của người dùng mà không cần biết thông tin đăng nhập của họ. OpenID Connect là một lớp xác thực được xây dựng trên OAuth2, cung cấp thêm thông tin về người dùng.

Luồng xác thực OAuth2

oauth2_openid_code

Hệ thống sử dụng OAuth2 và OpenID Connect để xác thực và phân quyền giữa các dịch vụ. Mỗi dịch vụ tự quản lý phân quyền và sử dụng IAM (Identity Access Management) để hỗ trợ xác thực người dùng.

Chọn luồng xác thực OAuth2

xem phần đề để chọn luồng xác thực phù hợp với ứng dụng hoặc dịch vụ của mình.

tham khảo: https://auth0.com/docs/api-auth/which-oauth-flow-to-use

OpenID Configuration

Xem phần này để biết cấu hình kết nối với Identity Provider để thực hiện xác thực v.v.

{
    issuer: "https://accounts.vdatlab.com/auth/realms/vdatlab.com",
    authorization_endpoint: "https://accounts.vdatlab.com/auth/realms/vdatlab.com/protocol/openid-connect/auth",
    token_endpoint: "https://accounts.vdatlab.com/auth/realms/vdatlab.com/protocol/openid-connect/token",
    token_introspection_endpoint: "https://accounts.vdatlab.com/auth/realms/vdatlab.com/protocol/openid-connect/token/introspect",
    userinfo_endpoint: "https://accounts.vdatlab.com/auth/realms/vdatlab.com/protocol/openid-connect/userinfo",
    end_session_endpoint: "https://accounts.vdatlab.com/auth/realms/vdatlab.com/protocol/openid-connect/logout",
    jwks_uri: "https://accounts.vdatlab.com/auth/realms/vdatlab.com/protocol/openid-connect/certs",
    check_session_iframe: "https://accounts.vdatlab.com/auth/realms/vdatlab.com/protocol/openid-connect/login-status-iframe.html",
    grant_types_supported: [
        "authorization_code",
        "implicit",
        "refresh_token",
        "password",
        "client_credentials"
    ],
    response_types_supported: [
        "code",
        "none",
        "id_token",
        "token",
        "id_token token",
        "code id_token",
        "code token",
        "code id_token token"
    ],
    ...
}

cấu hình đầy đủ: https://accounts.vdatlab.com/auth/realms/vdatlab.com/.well-known/openid-configuration

Hướng dẫn cấu hình 1 số biến cho các flow cơ bản

Flow xử dụng (ví dụ trong Postman):

  • đối với Web app => Implicit
  • đố i với service => Client Credentials

trong đó:

  • đối với luồng Implicit: lấy thông tin authorization_endpoint từ config và clientId, callback_url, scopes/defaultClientScopes từ thông tin client
  • đối với luồng Client Credentials: thông tin token_endpoint từ config và clientId, scopes/defaultClientScopes từ thông tin client; client_secret được cấp bởi admin

9.2 - Secret Management

Secret management is the process of managing secrets in a Kubernetes cluster.

9.2.1 - SOPS: Secrets OPerationS

Hướng dẫn sử dụng Mozilla SOPS để quản lý bí mật an toàn

SOPS (Secrets OPerationS)

SOPS là một công cụ mã nguồn mở được phát triển bởi Mozilla để mã hóa và quản lý các bí mật (secrets) trong tệp cấu hình và tệp văn bản.

Tính năng chính

  • Mã hóa tệp: Mã hóa các giá trị trong tệp YAML, JSON, ENV, INI và binary
  • Hỗ trợ nhiều phương thức mã hóa: AWS KMS, GCP KMS, Azure Key Vault, PGP
  • Mã hóa có chọn lọc: Chỉ mã hóa các giá trị, giữ nguyên cấu trúc tệp
  • Quản lý phiên bản: Theo dõi thay đổi với diff có thể đọc được

Lợi ích

  • Lưu trữ bí mật an toàn trong hệ thống quản lý phiên bản
  • Dễ dàng chia sẻ bí mật trong nhóm
  • Tích hợp tốt với các công cụ CI/CD và GitOps
  • Hỗ trợ nhiều định dạng tệp phổ biến

9.3 - VPN

9.3.1 - Tailscale

Tailscale is a Mesh VPN that automatically creates a secure network between your devices.

Tailscale

Installation

brew install tailscale

Configuration

tailscale up

9.4 - Zero Trust Network Architecture (ZTNA)

10 - Operations

10.1 - Ansible

Hướng dẫn sử dụng Ansible và các thực hành tốt nhất

Ansible

Ansible là một công cụ tự động hóa IT mã nguồn mở, giúp quản lý cấu hình, triển khai ứng dụng và điều phối nhiệm vụ.

Tính năng chính

  • Agentless: Không yêu cầu cài đặt agent trên các máy đích
  • Declarative: Sử dụng YAML để mô tả trạng thái mong muốn
  • Idempotent: Có thể chạy nhiều lần mà không gây ra tác dụng phụ
  • Extensible: Dễ dàng mở rộng với modules và plugins

Playbooks

Playbooks là tệp YAML định nghĩa các nhiệm vụ tự động hóa trong Ansible.

Inventory

Inventory là danh sách các máy chủ mà Ansible quản lý, có thể được nhóm và phân cấp.

10.2 - Kubernetes

Kubernetes container orchestration platform basics and concepts

Overview

Kubernetes is an open-source container orchestration platform for automating deployment, scaling, and management of containerized applications.

Basic Concepts

ConceptDescription
PodSmallest deployable unit that can contain one or more containers
NodeWorker machine in the Kubernetes cluster
ClusterSet of nodes that run containerized applications
DeploymentManages the desired state for Pods and ReplicaSets
ServiceDefines a logical set of Pods and a policy to access them
NamespaceVirtual cluster within a physical cluster

Common Commands

CommandDescription
kubectl get podsList all pods in the current namespace
kubectl apply -f file.yamlCreate or update resources from a file
kubectl describe pod <pod-name>Show detailed information about a pod
kubectl logs <pod-name>Print the logs from a container in a pod
kubectl exec -it <pod-name> -- /bin/bashExecute a command in a container

10.2.1 - Port Forward Kubernetes

Cấu hình port forward tạo kết nối đến ứng dụng triển khai trên Kubernetes cluster

Syntax

NS=<namespace>; kubectl -n $NS port-forward $(kubectl -n $NS get pods -l app=<[production,staging,production-postgres,staging-postgres]> | awk 'NR==2{print$1}') <local_port>:<container_port>
  1. Ví dụ tạo kết nối đến DB staging của Collector

điền NS=collector-8148254 APP=staging-postgres

lệnh: NS=collector-8148254 APP=staging-postgres; kubectl -n $NS port-forward $(kubectl -n $NS get pods -l app=$APP | awk 'NR==2{print$1}') 5432:5432

  1. Tạo kết nối đế n ứng dụng collector staging để truy cập bằng localhost:8080

lệnh: NS=collector-8148254 APP=staging; kubectl -n $NS port-forward $(kubectl -n $NS get pods -l app=$APP | awk 'NR==2{print$1}') 8080:5000

10.3 - OpenTelemetry

Hướng dẫn về OpenTelemetry và cách triển khai trong hệ thống

OpenTelemetry

OpenTelemetry (OTel) là một framework mã nguồn mở để thu thập dữ liệu telemetry từ các ứng dụng và dịch vụ. OTel cung cấp các API, thư viện, agent và công cụ thu thập để tạo, quản lý và xuất dữ liệu telemetry (logs, metrics, và traces) đến các backend phân tích.

Thành phần chính

  • Traces: Theo dõi luồng yêu cầu qua các dịch vụ
  • Metrics: Thu thập dữ liệu số liệu về hiệu suất hệ thống
  • Logs: Ghi lại các sự kiện xảy ra trong hệ thống

Lợi ích

  • Chuẩn hóa việc thu thập dữ liệu telemetry
  • Giảm thiểu vendor lock-in
  • Tích hợp dễ dàng với nhiều backend phân tích
  • Hỗ trợ đa ngôn ngữ lập trình

10.4 - GitOps

Example workflow

sequenceDiagram
    participant Dev as Developer
    participant GL as GitLab
    participant TFC as Terraform Cloud
    participant CF as Cloudflare
    
    Dev->>GL: Update members.yaml
    GL->>GL: Merge to master
    GL->>TFC: Trigger pipeline
    TFC->>CF: Update Zero Trust access permissions
    Note over CF: Application access policies updated

In this example, a developer updates the members.yaml file, which contains the list of members who have access to the site. Another developer review then merges the changes to the master branch, triggering a pipeline in Terraform Cloud. The pipeline updates the Zero Trust access permissions in Cloudflare, updating the application access policies.