Introduction: Building the Complete GitOps Stack
In Part 1 of this series, we established a robust Harbor container registry on RKE2 using SUSE Application Collection. Now we’ll complete the enterprise GitOps stack by integrating ArgoCD with Harbor, creating a secure, automated continuous deployment pipeline that meets enterprise requirements.
This integration combines Harbor’s enterprise-grade container security features with ArgoCD’s declarative GitOps workflows, providing a comprehensive platform for automated application deployment with built-in security scanning, policy enforcement, and compliance capabilities.
Why ArgoCD with Harbor for Enterprise GitOps
The ArgoCD-Harbor integration provides critical enterprise capabilities:
- Secure Image Management: Automated vulnerability scanning before deployment
- Policy Enforcement: Pre-deployment security validation and compliance checks
- Image Promotion: Controlled progression from development to production registries
- Audit Trail: Complete deployment history with image provenance tracking
- Multi-Environment GitOps: Consistent deployment patterns across environments
Architecture Overview: Complete GitOps Stack
┌────────────────────────────────────────────────────────────────────────┐
│ GitOps Workflow Architecture │
├────────────────────────────────────────────────────────────────────────┤
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ GitHub │ │ CI Pipeline │ │ Harbor │ │ ArgoCD │ │
│ │ Repository │───▶│ Build & Test │───▶│ Registry │───▶│ Deployment │ │
│ │ - Apps │ │ - Security │ │ - Scanning │ │ - Sync │ │
│ │ - Manifests │ │ - Quality │ │ - Signing │ │ - Rollback │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
├────────────────────────────────────────────────────────────────────────┤
│ RKE2 Kubernetes Cluster │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ ArgoCD │ │ Harbor │ │ Application │ │ Monitoring │ │
│ │ - Server │ │ - Core │ │ Workloads │ │ - Prometheus│ │
│ │ - Repo Srv │ │ - Registry │ │ - Services │ │ - Grafana │ │
│ │ - App Ctrl │ │ - Scanner │ │ - Ingress │ │ - Alerts │ │
│ │ - Redis │ │ - Notary │ │ - Storage │ │ - Logs │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ └──────────────┘ │
└────────────────────────────────────────────────────────────────────────┘
Part 1: ArgoCD Installation and Configuration
Prerequisites and Environment Validation
Before proceeding, ensure you have the Harbor setup from Part 1 and validate your environment:
# Verify Harbor is running and accessible
kubectl get pods -n harbor-system
kubectl get ingress -n harbor-system
# Test Harbor API connectivity
curl -k https://harbor.yourdomain.com/api/v2.0/systeminfo
# Verify sufficient cluster resources for ArgoCD
kubectl top nodes
kubectl get storageclass
ArgoCD Installation via SUSE Application Collection
Install ArgoCD using the SUSE Application Collection for enterprise support:
# Verify SUSE Application Collection repository
helm repo list | grep suse-application-collection
helm search repo suse-application-collection/argo-cd
# Create ArgoCD namespace with proper labels
kubectl create namespace argocd-system
kubectl label namespace argocd-system name=argocd-system
# Label nodes for ArgoCD workload placement
kubectl label nodes worker-node-1 argocd.io/workload=server
kubectl label nodes worker-node-2 argocd.io/workload=server
kubectl label nodes worker-node-3 argocd.io/workload=repo-server
Create ArgoCD values configuration:
# argocd-values.yaml
global:
domain: argocd.yourdomain.com
server:
replicas: 2
nodeSelector:
argocd.io/workload: server
ingress:
enabled: true
ingressClassName: nginx
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod-harbor"
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
hosts:
- argocd.yourdomain.com
tls:
- secretName: argocd-server-tls
hosts:
- argocd.yourdomain.com
repoServer:
replicas: 2
nodeSelector:
argocd.io/workload: repo-server
# Harbor registry access configuration
env:
- name: DOCKER_CONFIG
value: /tmp/.docker
volumeMounts:
- name: harbor-registry-config
mountPath: /tmp/.docker
readOnly: true
volumes:
- name: harbor-registry-config
secret:
secretName: harbor-registry-config
# Install ArgoCD
helm upgrade --install argocd \
suse-application-collection/argo-cd \
--namespace argocd-system \
--values argocd-values.yaml \
--timeout 20m \
--wait
# Get initial admin password
kubectl -n argocd-system get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d
Part 2: Harbor-ArgoCD Integration
Creating Harbor Robot Accounts
Create dedicated robot accounts in Harbor for ArgoCD automation via Harbor UI:
- Navigate to Harbor UI → Administration → Robot Accounts
- Create new robot account:
argocd-deployer
- Set expiration to 1 year
- Grant permissions: Pull on all projects, Push on dev projects
- Save robot token securely
Configuring Registry Credentials
# Create Harbor registry secret for ArgoCD
kubectl create secret docker-registry harbor-registry-config \
--docker-server=harbor.yourdomain.com \
--docker-username="robot\$argocd-deployer" \
--docker-password="[robot-token-from-harbor]" \
--namespace=argocd-system
# Create image pull secrets for application namespaces
for ns in default production staging development; do
kubectl create namespace $ns --dry-run=client -o yaml | kubectl apply -f -
kubectl create secret docker-registry harbor-registry-secret \
--docker-server=harbor.yourdomain.com \
--docker-username="robot\$argocd-deployer" \
--docker-password="[robot-token-from-harbor]" \
--namespace=$ns \
--dry-run=client -o yaml | kubectl apply -f -
kubectl patch serviceaccount default -n $ns \
-p '{"imagePullSecrets": [{"name": "harbor-registry-secret"}]}'
done
Part 3: GitOps Workflows and Applications
Sample Application with Harbor Images
# sample-app/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
imagePullSecrets:
- name: harbor-registry-secret
containers:
- name: web-app
image: harbor.yourdomain.com/library/nginx:1.25.3
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
securityContext:
runAsNonRoot: true
runAsUser: 101
readOnlyRootFilesystem: true
---
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
selector:
app: web-app
ports:
- protocol: TCP
port: 80
targetPort: 80
ArgoCD Application Configuration
# argocd-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: web-app
namespace: argocd-system
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
source:
repoURL: https://github.com/your-org/k8s-manifests.git
targetRevision: HEAD
path: sample-app
destination:
server: https://kubernetes.default.svc
namespace: default
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- CreateNamespace=true
# Deploy ArgoCD Application
kubectl apply -f argocd-application.yaml
# Monitor application sync
kubectl get application web-app -n argocd-system
Part 4: CI/CD Pipeline Integration
Complete GitHub Actions Workflow
# .github/workflows/ci-cd-pipeline.yaml
name: CI/CD Pipeline with Harbor and ArgoCD
on:
push:
branches: [ main, develop ]
env:
HARBOR_REGISTRY: harbor.yourdomain.com
HARBOR_PROJECT: library
IMAGE_NAME: web-app
jobs:
build-and-scan:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Harbor
uses: docker/login-action@v3
with:
registry: ${{ env.HARBOR_REGISTRY }}
username: ${{ secrets.HARBOR_USERNAME }}
password: ${{ secrets.HARBOR_PASSWORD }}
- name: Build and push image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
- name: Wait for Harbor scan
run: |
sleep 30
# Check vulnerability scan results
SCAN_RESULT=$(curl -s -u "${{ secrets.HARBOR_USERNAME }}:${{ secrets.HARBOR_PASSWORD }}" \
"${{ env.HARBOR_REGISTRY }}/api/v2.0/projects/${{ env.HARBOR_PROJECT }}/repositories/${{ env.IMAGE_NAME }}/artifacts/${{ github.sha }}/scan")
CRITICAL=$(echo $SCAN_RESULT | jq -r '.scan_overview."application/vnd.security.vulnerability.report; version=1.1".summary.critical // 0')
if [ "$CRITICAL" -gt 0 ]; then
echo "❌ Image has $CRITICAL critical vulnerabilities"
exit 1
fi
update-manifests:
needs: build-and-scan
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout manifests repository
uses: actions/checkout@v4
with:
repository: your-org/k8s-manifests
token: ${{ secrets.MANIFEST_REPO_TOKEN }}
- name: Update image tag
run: |
sed -i "s|image: ${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:.*|image: ${{ env.HARBOR_REGISTRY }}/${{ env.HARBOR_PROJECT }}/${{ env.IMAGE_NAME }}:${{ github.sha }}|" sample-app/deployment.yaml
- name: Commit and push changes
run: |
git config user.name "GitHub Actions"
git config user.email "actions@github.com"
git add .
git commit -m "Update ${{ env.IMAGE_NAME }} to ${{ github.sha }}"
git push
Part 5: Production Operations
Monitoring and Observability
# Key ArgoCD metrics to monitor:
- argocd_app_health_status # Application health
- argocd_app_sync_total # Sync operations
- argocd_git_request_duration # Repository performance
- argocd_app_reconcile_bucket # Controller performance
# Essential alerts:
- ArgoCD application sync failures
- Harbor registry downtime
- Critical vulnerabilities in deployed images
- Certificate expiration warnings
Security and Compliance
# OPA Gatekeeper policy for Harbor images only
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: harborimageorigin
spec:
crd:
spec:
names:
kind: HarborImageOrigin
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package harborimageorigin
violation[{"msg": msg}] {
input.review.kind.kind == "Deployment"
container := input.review.object.spec.template.spec.containers[_]
image := container.image
not startswith(image, "harbor.yourdomain.com/")
msg := sprintf("Image %v must come from Harbor registry", [image])
}
Backup and Disaster Recovery
# ArgoCD backup script
#!/bin/bash
echo "Starting ArgoCD backup..."
# Export applications, projects, repositories, clusters
argocd app list -o json > applications.json
argocd proj list -o json > projects.json
argocd repo list -o json > repositories.json
argocd cluster list -o json > clusters.json
# Create backup archive
tar -czf argocd-backup-$(date +%Y%m%d).tar.gz *.json
# Upload to backup storage
aws s3 cp argocd-backup-$(date +%Y%m%d).tar.gz s3://backup-bucket/argocd/
Troubleshooting Common Issues
# Common troubleshooting commands:
# Check ArgoCD application status
kubectl get applications -n argocd-system
argocd app get web-app
# Verify image pull secrets
kubectl get secrets | grep harbor
kubectl describe pod [failing-pod]
# Test Harbor registry connectivity
kubectl run -it --rm debug --image=busybox --restart=Never -- \
wget -O- https://harbor.yourdomain.com/v2/
# Check ArgoCD sync issues
argocd app diff web-app
argocd app sync web-app --dry-run
# Review logs
kubectl logs -n argocd-system deployment/argocd-application-controller
kubectl logs -n harbor-system deployment/harbor-core
Production Best Practices
Security Best Practices
- Image Security: Mandatory vulnerability scanning with severity thresholds
- Access Control: Dedicated robot accounts with minimal permissions
- Network Security: Network policies restricting component communication
- Content Trust: Image signing for production deployments
- Secret Management: Regular credential rotation
Operational Excellence
- Monitoring: Application health and sync status monitoring
- Alerting: Proactive alerts for failures and security issues
- Backup: Automated configuration and data backups
- Documentation: Current runbooks and procedures
- Testing: Regular disaster recovery testing
Conclusion
You now have a production-ready GitOps platform that combines Harbor’s enterprise container security with ArgoCD’s declarative deployment automation. This integration provides:
- Complete Security Pipeline: From vulnerability scanning to policy enforcement
- Automated Operations: Self-healing deployments with monitoring
- Enterprise Integration: Authentication, RBAC, and audit trails
- Scalable Architecture: High-availability supporting large deployments
- Developer Productivity: GitOps workflows enabling rapid delivery
This platform serves as the foundation for modern DevOps practices, enabling secure, automated application delivery that scales with enterprise requirements. The Harbor-ArgoCD integration creates a robust deployment pipeline suitable for demanding production environments.
Next Steps
Consider exploring these advanced topics to further enhance your GitOps platform:
- Multi-Cluster Management: Extend ArgoCD across multiple Kubernetes clusters
- Progressive Delivery: Implement canary and blue-green deployments with Argo Rollouts
- Policy as Code: Expand governance with comprehensive OPA policies
- Supply Chain Security: Integrate SLSA compliance and SBOM generation
- Advanced Observability: Implement distributed tracing and APM