448 lines
10 KiB
Markdown
448 lines
10 KiB
Markdown
# Kubernetes Deployment Example for CMS API
|
|
|
|
## 🔐 ایجاد Secrets
|
|
|
|
### برای Staging:
|
|
|
|
```bash
|
|
kubectl create secret generic cms-secrets \
|
|
--from-literal=db-connection="Data Source=STAGING_SERVER;Initial Catalog=Foursat_Staging;User ID=sa;Password=STAGING_PASSWORD;MultipleActiveResultSets=True;Encrypt=False" \
|
|
--from-literal=jwt-key="YOUR_STAGING_JWT_KEY" \
|
|
--from-literal=kavenegar-key="YOUR_STAGING_KAVENEGAR_KEY" \
|
|
--from-literal=daya-key="YOUR_STAGING_DAYA_KEY" \
|
|
--from-literal=chatika-key="YOUR_STAGING_CHATIKA_KEY" \
|
|
--from-literal=sentry-dsn="YOUR_STAGING_SENTRY_DSN" \
|
|
--from-literal=slack-webhook="YOUR_STAGING_SLACK_WEBHOOK" \
|
|
--from-literal=seq-key="YOUR_STAGING_SEQ_KEY" \
|
|
--namespace=staging
|
|
```
|
|
|
|
### برای Production:
|
|
|
|
```bash
|
|
kubectl create secret generic cms-secrets \
|
|
--from-literal=db-connection="Data Source=PRODUCTION_SERVER;Initial Catalog=Foursat;User ID=sa;Password=PRODUCTION_PASSWORD;MultipleActiveResultSets=True;Encrypt=True" \
|
|
--from-literal=jwt-key="YOUR_PRODUCTION_JWT_KEY" \
|
|
--from-literal=kavenegar-key="YOUR_PRODUCTION_KAVENEGAR_KEY" \
|
|
--from-literal=daya-key="YOUR_PRODUCTION_DAYA_KEY" \
|
|
--from-literal=chatika-key="YOUR_PRODUCTION_CHATIKA_KEY" \
|
|
--from-literal=sentry-dsn="YOUR_PRODUCTION_SENTRY_DSN" \
|
|
--from-literal=slack-webhook="YOUR_PRODUCTION_SLACK_WEBHOOK" \
|
|
--from-literal=seq-key="YOUR_PRODUCTION_SEQ_KEY" \
|
|
--from-literal=smtp-username="production@domain.com" \
|
|
--from-literal=smtp-password="YOUR_SMTP_PASSWORD" \
|
|
--namespace=production
|
|
```
|
|
|
|
---
|
|
|
|
## 📄 Deployment Manifest
|
|
|
|
### cms-deployment-staging.yaml
|
|
|
|
```yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: cms-api
|
|
namespace: staging
|
|
labels:
|
|
app: cms-api
|
|
environment: staging
|
|
spec:
|
|
replicas: 2
|
|
selector:
|
|
matchLabels:
|
|
app: cms-api
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: cms-api
|
|
environment: staging
|
|
spec:
|
|
containers:
|
|
- name: cms
|
|
image: your-registry/cms-api:staging-latest
|
|
ports:
|
|
- containerPort: 5000
|
|
name: grpc
|
|
protocol: TCP
|
|
- containerPort: 8080
|
|
name: http
|
|
protocol: TCP
|
|
env:
|
|
# Environment
|
|
- name: ASPNETCORE_ENVIRONMENT
|
|
value: "Staging"
|
|
|
|
# Database
|
|
- name: ConnectionStrings__DefaultConnection
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: db-connection
|
|
|
|
# JWT
|
|
- name: JwtSecurityKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: jwt-key
|
|
|
|
# SMS
|
|
- name: Sms__KavenegarApiKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: kavenegar-key
|
|
|
|
# Daya API
|
|
- name: DayaApi__MerchantPermissionKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: daya-key
|
|
|
|
# Chatika
|
|
- name: Chatika__ApiKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: chatika-key
|
|
|
|
# Monitoring
|
|
- name: Monitoring__SentryDsn
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: sentry-dsn
|
|
|
|
- name: Monitoring__SlackWebhookUrl
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: slack-webhook
|
|
|
|
# Seq
|
|
- name: Seq__ApiKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: seq-key
|
|
|
|
resources:
|
|
requests:
|
|
memory: "512Mi"
|
|
cpu: "250m"
|
|
limits:
|
|
memory: "1Gi"
|
|
cpu: "500m"
|
|
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health/live
|
|
port: 8080
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health/ready
|
|
port: 8080
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 5
|
|
timeoutSeconds: 3
|
|
failureThreshold: 3
|
|
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: cms-api-service
|
|
namespace: staging
|
|
spec:
|
|
selector:
|
|
app: cms-api
|
|
ports:
|
|
- name: grpc
|
|
port: 5000
|
|
targetPort: 5000
|
|
protocol: TCP
|
|
- name: http
|
|
port: 8080
|
|
targetPort: 8080
|
|
protocol: TCP
|
|
type: ClusterIP
|
|
|
|
---
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: cms-api-ingress
|
|
namespace: staging
|
|
annotations:
|
|
kubernetes.io/ingress.class: nginx
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
spec:
|
|
tls:
|
|
- hosts:
|
|
- cms-staging.domain.com
|
|
secretName: cms-staging-tls
|
|
rules:
|
|
- host: cms-staging.domain.com
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: cms-api-service
|
|
port:
|
|
number: 8080
|
|
```
|
|
|
|
### cms-deployment-production.yaml
|
|
|
|
```yaml
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: cms-api
|
|
namespace: production
|
|
labels:
|
|
app: cms-api
|
|
environment: production
|
|
spec:
|
|
replicas: 3 # بیشتر برای production
|
|
selector:
|
|
matchLabels:
|
|
app: cms-api
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: cms-api
|
|
environment: production
|
|
spec:
|
|
containers:
|
|
- name: cms
|
|
image: your-registry/cms-api:production-latest
|
|
ports:
|
|
- containerPort: 5000
|
|
name: grpc
|
|
- containerPort: 8080
|
|
name: http
|
|
env:
|
|
- name: ASPNETCORE_ENVIRONMENT
|
|
value: "Production"
|
|
|
|
# همان تنظیمات secrets مثل staging
|
|
- name: ConnectionStrings__DefaultConnection
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: db-connection
|
|
|
|
- name: JwtSecurityKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: jwt-key
|
|
|
|
- name: Sms__KavenegarApiKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: kavenegar-key
|
|
|
|
- name: DayaApi__MerchantPermissionKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: daya-key
|
|
|
|
- name: Chatika__ApiKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: chatika-key
|
|
|
|
- name: Monitoring__SentryDsn
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: sentry-dsn
|
|
|
|
- name: Monitoring__SlackWebhookUrl
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: slack-webhook
|
|
|
|
- name: Seq__ApiKey
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: seq-key
|
|
|
|
# Email credentials for production
|
|
- name: Email__SmtpUsername
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: smtp-username
|
|
|
|
- name: Email__SmtpPassword
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: cms-secrets
|
|
key: smtp-password
|
|
|
|
resources:
|
|
requests:
|
|
memory: "1Gi"
|
|
cpu: "500m"
|
|
limits:
|
|
memory: "2Gi"
|
|
cpu: "1000m"
|
|
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health/live
|
|
port: 8080
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health/ready
|
|
port: 8080
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 5
|
|
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: cms-api-service
|
|
namespace: production
|
|
spec:
|
|
selector:
|
|
app: cms-api
|
|
ports:
|
|
- name: grpc
|
|
port: 5000
|
|
targetPort: 5000
|
|
- name: http
|
|
port: 8080
|
|
targetPort: 8080
|
|
type: ClusterIP
|
|
|
|
---
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: cms-api-ingress
|
|
namespace: production
|
|
annotations:
|
|
kubernetes.io/ingress.class: nginx
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
spec:
|
|
tls:
|
|
- hosts:
|
|
- cms.domain.com
|
|
secretName: cms-production-tls
|
|
rules:
|
|
- host: cms.domain.com
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: cms-api-service
|
|
port:
|
|
number: 8080
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 Deploy Commands
|
|
|
|
### Staging:
|
|
```bash
|
|
kubectl apply -f cms-deployment-staging.yaml
|
|
kubectl get pods -n staging
|
|
kubectl logs -f deployment/cms-api -n staging
|
|
```
|
|
|
|
### Production:
|
|
```bash
|
|
kubectl apply -f cms-deployment-production.yaml
|
|
kubectl get pods -n production
|
|
kubectl logs -f deployment/cms-api -n production
|
|
```
|
|
|
|
---
|
|
|
|
## 🔄 CI/CD Integration
|
|
|
|
### GitLab CI Example:
|
|
|
|
```yaml
|
|
stages:
|
|
- build
|
|
- deploy-staging
|
|
- deploy-production
|
|
|
|
variables:
|
|
DOCKER_REGISTRY: your-registry.azurecr.io
|
|
IMAGE_NAME: cms-api
|
|
|
|
build:
|
|
stage: build
|
|
script:
|
|
- docker build -t $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA .
|
|
- docker push $DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA
|
|
|
|
deploy-staging:
|
|
stage: deploy-staging
|
|
only:
|
|
- kub-stage
|
|
script:
|
|
- kubectl set image deployment/cms-api cms=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n staging
|
|
- kubectl rollout status deployment/cms-api -n staging
|
|
|
|
deploy-production:
|
|
stage: deploy-production
|
|
only:
|
|
- production
|
|
when: manual # نیاز به تأیید دستی
|
|
script:
|
|
- kubectl set image deployment/cms-api cms=$DOCKER_REGISTRY/$IMAGE_NAME:$CI_COMMIT_SHA -n production
|
|
- kubectl rollout status deployment/cms-api -n production
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 Monitoring
|
|
|
|
### Check deployment status:
|
|
```bash
|
|
kubectl get deployments -n staging
|
|
kubectl get pods -n staging -l app=cms-api
|
|
kubectl describe pod <pod-name> -n staging
|
|
```
|
|
|
|
### View logs:
|
|
```bash
|
|
kubectl logs -f deployment/cms-api -n staging
|
|
kubectl logs --tail=100 deployment/cms-api -n production
|
|
```
|
|
|
|
### Check configuration:
|
|
```bash
|
|
kubectl exec -it <pod-name> -n staging -- env | grep ASPNETCORE
|
|
```
|