DevOps Practices trong Java
1. Lý thuyết và Khái niệm Cơ bản
1.1 DevOps Principles
- Continuous Integration (CI)
- Continuous Delivery (CD)
- Infrastructure as Code (IaC)
- Monitoring và Logging
- Automated Testing
- Security Integration (DevSecOps)
- Collaboration và Communication
1.2 DevOps Pipeline
- Source Control
- Build Automation
- Test Automation
- Deployment Automation
- Infrastructure Automation
- Monitoring và Feedback
2. Best Practices và Design Patterns
2.1 CI/CD Configuration
# .github/workflows/ci-cd.yml
name: Java CI/CD Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
- name: Build with Maven
run: mvn -B package --file pom.xml
- name: Run Tests
run: mvn test
- name: Build Docker image
run: docker build -t myapp:${{ github.sha }} .
- name: Push to Registry
run: |
docker login -u ${{ secrets.DOCKER_USER }} -p ${{ secrets.DOCKER_PASSWORD }}
docker push myapp:${{ github.sha }}
2.2 Docker Configuration
# Dockerfile
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
3. Anti-patterns và Common Pitfalls
3.1 DevOps Anti-patterns
- Manual Deployment Steps
- No Version Control
- Inconsistent Environments
- No Automated Testing
- Poor Monitoring
- Lack of Documentation
3.2 Security Anti-patterns
# Bad Practice: Hardcoded Credentials
spring:
datasource:
url: jdbc:postgresql://localhost:5432/mydb
username: admin
password: secretpassword # Never hardcode passwords
# Good Practice: Use Environment Variables
spring:
datasource:
url: ${DB_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
4. Ví dụ Code Thực tế
4.1 Kubernetes Configuration
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: java-app
spec:
replicas: 3
selector:
matchLabels:
app: java-app
template:
metadata:
labels:
app: java-app
spec:
containers:
- name: java-app
image: myapp:latest
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 60
periodSeconds: 20
4.2 Monitoring Configuration
# prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'spring-actuator'
metrics_path: '/actuator/prometheus'
static_configs:
- targets: ['localhost:8080']
# grafana-dashboard.json
{
"annotations": {
"list": []
},
"panels": [
{
"title": "JVM Memory Usage",
"type": "graph",
"datasource": "Prometheus",
"targets": [
{
"expr": "jvm_memory_used_bytes",
"legendFormat": "{{area}}"
}
]
}
]
}
5. Use Cases và Scenarios
5.1 Microservices Deployment
# docker-compose.yml
version: '3.8'
services:
api-gateway:
build: ./api-gateway
ports:
- "8080:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
depends_on:
- service-registry
service-registry:
build: ./service-registry
ports:
- "8761:8761"
order-service:
build: ./order-service
environment:
- SPRING_PROFILES_ACTIVE=prod
- EUREKA_CLIENT_SERVICEURL_DEFAULTZONE=http://service-registry:8761/eureka/
depends_on:
- service-registry
- order-db
order-db:
image: postgres:13
environment:
- POSTGRES_DB=orderdb
- POSTGRES_USER=admin
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
volumes:
- order-data:/var/lib/postgresql/data
secrets:
- db_password
volumes:
order-data:
secrets:
db_password:
file: ./secrets/db_password.txt
5.2 CI/CD Pipeline
// Jenkinsfile
pipeline {
agent any
environment {
DOCKER_REGISTRY = 'registry.example.com'
APP_NAME = 'java-app'
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
stage('Test') {
steps {
sh 'mvn test'
}
post {
always {
junit '**/target/surefire-reports/*.xml'
}
}
}
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('SonarQube') {
sh 'mvn sonar:sonar'
}
}
}
stage('Build Docker Image') {
steps {
script {
docker.build("${DOCKER_REGISTRY}/${APP_NAME}:${BUILD_NUMBER}")
}
}
}
stage('Deploy to Staging') {
when {
branch 'develop'
}
steps {
sh "kubectl apply -f k8s/staging/"
}
}
stage('Deploy to Production') {
when {
branch 'main'
}
steps {
timeout(time: 1, unit: 'HOURS') {
input message: 'Approve production deployment?'
}
sh "kubectl apply -f k8s/production/"
}
}
}
post {
always {
cleanWs()
}
success {
slackSend channel: '#deployments',
color: 'good',
message: "Deployment successful: ${env.JOB_NAME} ${env.BUILD_NUMBER}"
}
failure {
slackSend channel: '#deployments',
color: 'danger',
message: "Deployment failed: ${env.JOB_NAME} ${env.BUILD_NUMBER}"
}
}
}
6.1 Resource Management
# kubernetes-resources.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi
---
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-limit-range
spec:
limits:
- default:
cpu: 500m
memory: 512Mi
defaultRequest:
cpu: 200m
memory: 256Mi
type: Container
6.2 Scaling Configuration
# autoscaling.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: java-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: java-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
7. Security Considerations
7.1 Security Scanning
# security-scan.yml
name: Security Scan
on:
push:
branches: [ main ]
schedule:
- cron: '0 0 * * *'
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run OWASP Dependency Check
uses: dependency-check/Dependency-Check_Action@main
with:
project: 'MyApp'
path: '.'
format: 'HTML'
- name: Run Container Scan
uses: azure/container-scan@v0
with:
image-name: myapp:latest
7.2 Network Policies
# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-network-policy
spec:
podSelector:
matchLabels:
app: java-app
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
role: database
ports:
- protocol: TCP
port: 5432
8. Testing Strategies
8.1 Integration Testing
@SpringBootTest
public class DeploymentTest {
@Test
public void testDeploymentConfiguration() {
// Test environment variables
assertNotNull(System.getenv("DB_URL"));
assertNotNull(System.getenv("DB_USERNAME"));
// Test application properties
@Value("${spring.datasource.url}")
String dbUrl;
assertEquals(System.getenv("DB_URL"), dbUrl);
}
}
8.2 Infrastructure Testing
# infrastructure-test.yml
name: Infrastructure Tests
on:
pull_request:
paths:
- 'terraform/**'
- 'kubernetes/**'
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Terraform
uses: hashicorp/setup-terraform@v1
- name: Terraform Format
run: terraform fmt -check
- name: Terraform Init
run: terraform init
- name: Terraform Validate
run: terraform validate
- name: Run tfsec
uses: aquasecurity/tfsec-action@v1.0.0
9. Monitoring và Troubleshooting
9.1 Logging Configuration
# fluentd-config.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentd-config
data:
fluent.conf: |
<source>
@type tail
path /var/log/containers/*.log
pos_file /var/log/fluentd-containers.log.pos
tag kubernetes.*
read_from_head true
<parse>
@type json
time_key time
time_format %Y-%m-%dT%H:%M:%S.%NZ
</parse>
</source>
<match kubernetes.**>
@type elasticsearch
host elasticsearch-logging
port 9200
logstash_format true
logstash_prefix k8s
<buffer>
@type file
path /var/log/fluentd-buffers/kubernetes.system.buffer
flush_mode interval
retry_type exponential_backoff
flush_interval 5s
retry_forever false
retry_max_interval 30
chunk_limit_size 2M
queue_limit_length 8
overflow_action block
</buffer>
</match>
9.2 Alerting Rules
# alerting-rules.yml
groups:
- name: JavaAppAlerts
rules:
- alert: HighCPUUsage
expr: container_cpu_usage_seconds_total{container="java-app"} > 0.8
for: 5m
labels:
severity: warning
annotations:
summary: High CPU usage detected
description: Container {{ $labels.container }} has high CPU usage
- alert: HighMemoryUsage
expr: container_memory_usage_bytes{container="java-app"} > 1e9
for: 5m
labels:
severity: warning
annotations:
summary: High memory usage detected
description: Container {{ $labels.container }} has high memory usage
10. References và Further Reading
10.1 DevOps Resources
- The DevOps Handbook
- Continuous Delivery by Jez Humble
- Site Reliability Engineering (Google)
- Infrastructure as Code by Kief Morris
- The Phoenix Project
- Jenkins/GitHub Actions for CI/CD
- Docker/Kubernetes for Containerization
- Terraform for Infrastructure as Code
- Prometheus/Grafana for Monitoring
- ELK Stack for Logging
- SonarQube for Code Quality