apollo-deploy-integration
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseApollo Deploy Integration
Apollo 集成部署
Overview
概述
Deploy Apollo.io integrations to production environments with proper configuration, health checks, and rollback procedures.
将Apollo.io集成部署到生产环境,包含正确的配置、健康检查和回滚流程。
Deployment Platforms
部署平台
Vercel Deployment
Vercel 部署
json
// vercel.json
{
"env": {
"APOLLO_API_KEY": "@apollo-api-key"
},
"build": {
"env": {
"APOLLO_API_KEY": "@apollo-api-key"
}
}
}bash
undefinedjson
// vercel.json
{
"env": {
"APOLLO_API_KEY": "@apollo-api-key"
},
"build": {
"env": {
"APOLLO_API_KEY": "@apollo-api-key"
}
}
}bash
undefinedAdd secret to Vercel
向Vercel添加密钥
vercel secrets add apollo-api-key "your-api-key"
vercel secrets add apollo-api-key "your-api-key"
Deploy
部署
vercel --prod
undefinedvercel --prod
undefinedGoogle Cloud Run
Google Cloud Run
yaml
undefinedyaml
undefinedcloudbuild.yaml
cloudbuild.yaml
steps:
-
name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'gcr.io/$PROJECT_ID/apollo-service', '.']
-
name: 'gcr.io/cloud-builders/docker' args: ['push', 'gcr.io/$PROJECT_ID/apollo-service']
-
name: 'gcr.io/cloud-builders/gcloud' args:
- 'run'
- 'deploy'
- 'apollo-service'
- '--image=gcr.io/$PROJECT_ID/apollo-service'
- '--platform=managed'
- '--region=us-central1'
- '--set-secrets=APOLLO_API_KEY=apollo-api-key:latest'
- '--allow-unauthenticated'
```bashsteps:
-
name: 'gcr.io/cloud-builders/docker' args: ['build', '-t', 'gcr.io/$PROJECT_ID/apollo-service', '.']
-
name: 'gcr.io/cloud-builders/docker' args: ['push', 'gcr.io/$PROJECT_ID/apollo-service']
-
name: 'gcr.io/cloud-builders/gcloud' args:
- 'run'
- 'deploy'
- 'apollo-service'
- '--image=gcr.io/$PROJECT_ID/apollo-service'
- '--platform=managed'
- '--region=us-central1'
- '--set-secrets=APOLLO_API_KEY=apollo-api-key:latest'
- '--allow-unauthenticated'
```bashCreate secret in Google Cloud
在Google Cloud中创建密钥
gcloud secrets create apollo-api-key --data-file=-
echo -n "your-api-key" | gcloud secrets versions add apollo-api-key --data-file=-
gcloud secrets create apollo-api-key --data-file=-
echo -n "your-api-key" | gcloud secrets versions add apollo-api-key --data-file=-
Grant access to Cloud Run
为Cloud Run授予访问权限
gcloud secrets add-iam-policy-binding apollo-api-key
--member="serviceAccount:YOUR-SA@PROJECT.iam.gserviceaccount.com"
--role="roles/secretmanager.secretAccessor"
--member="serviceAccount:YOUR-SA@PROJECT.iam.gserviceaccount.com"
--role="roles/secretmanager.secretAccessor"
undefinedgcloud secrets add-iam-policy-binding apollo-api-key
--member="serviceAccount:YOUR-SA@PROJECT.iam.gserviceaccount.com"
--role="roles/secretmanager.secretAccessor"
--member="serviceAccount:YOUR-SA@PROJECT.iam.gserviceaccount.com"
--role="roles/secretmanager.secretAccessor"
undefinedAWS Lambda
AWS Lambda
yaml
undefinedyaml
undefinedserverless.yml
serverless.yml
service: apollo-integration
provider:
name: aws
runtime: nodejs20.x
region: us-east-1
environment:
APOLLO_API_KEY: ${ssm:/apollo/api-key~true}
functions:
search:
handler: src/handlers/search.handler
events:
- http:
path: /api/apollo/search
method: post
timeout: 30
enrich:
handler: src/handlers/enrich.handler
events:
- http:
path: /api/apollo/enrich
method: get
timeout: 30
```bashservice: apollo-integration
provider:
name: aws
runtime: nodejs20.x
region: us-east-1
environment:
APOLLO_API_KEY: ${ssm:/apollo/api-key~true}
functions:
search:
handler: src/handlers/search.handler
events:
- http:
path: /api/apollo/search
method: post
timeout: 30
enrich:
handler: src/handlers/enrich.handler
events:
- http:
path: /api/apollo/enrich
method: get
timeout: 30
```bashStore secret in SSM
将密钥存储到SSM
aws ssm put-parameter
--name "/apollo/api-key"
--type "SecureString"
--value "your-api-key"
--name "/apollo/api-key"
--type "SecureString"
--value "your-api-key"
aws ssm put-parameter
--name "/apollo/api-key"
--type "SecureString"
--value "your-api-key"
--name "/apollo/api-key"
--type "SecureString"
--value "your-api-key"
Deploy
部署
serverless deploy --stage production
undefinedserverless deploy --stage production
undefinedKubernetes
Kubernetes
yaml
undefinedyaml
undefinedk8s/deployment.yaml
k8s/deployment.yaml
apiVersion: apps/v1 kind: Deployment metadata: name: apollo-service spec: replicas: 3 selector: matchLabels: app: apollo-service template: metadata: labels: app: apollo-service spec: containers: - name: apollo-service image: your-registry/apollo-service:latest ports: - containerPort: 3000 env: - name: APOLLO_API_KEY valueFrom: secretKeyRef: name: apollo-secrets key: api-key livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /health/apollo port: 3000 initialDelaySeconds: 5 periodSeconds: 5 resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m"
apiVersion: v1
kind: Secret
metadata:
name: apollo-secrets
type: Opaque
stringData:
api-key: your-api-key # Use sealed-secrets in production
undefinedapiVersion: apps/v1 kind: Deployment metadata: name: apollo-service spec: replicas: 3 selector: matchLabels: app: apollo-service template: metadata: labels: app: apollo-service spec: containers: - name: apollo-service image: your-registry/apollo-service:latest ports: - containerPort: 3000 env: - name: APOLLO_API_KEY valueFrom: secretKeyRef: name: apollo-secrets key: api-key livenessProbe: httpGet: path: /health port: 3000 initialDelaySeconds: 10 periodSeconds: 10 readinessProbe: httpGet: path: /health/apollo port: 3000 initialDelaySeconds: 5 periodSeconds: 5 resources: requests: memory: "256Mi" cpu: "100m" limits: memory: "512Mi" cpu: "500m"
apiVersion: v1
kind: Secret
metadata:
name: apollo-secrets
type: Opaque
stringData:
api-key: your-api-key # 生产环境中使用sealed-secrets
undefinedHealth Check Endpoints
健康检查端点
typescript
// src/routes/health.ts
import { Router } from 'express';
import { apollo } from '../lib/apollo/client';
const router = Router();
// Basic health check
router.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Apollo-specific health check
router.get('/health/apollo', async (req, res) => {
try {
const start = Date.now();
await apollo.healthCheck();
const latency = Date.now() - start;
res.json({
status: 'ok',
apollo: {
connected: true,
latencyMs: latency,
},
});
} catch (error: any) {
res.status(503).json({
status: 'degraded',
apollo: {
connected: false,
error: error.message,
},
});
}
});
// Readiness check (for Kubernetes)
router.get('/ready', async (req, res) => {
try {
await apollo.healthCheck();
res.json({ ready: true });
} catch {
res.status(503).json({ ready: false });
}
});
export default router;typescript
// src/routes/health.ts
import { Router } from 'express';
import { apollo } from '../lib/apollo/client';
const router = Router();
// 基础健康检查
router.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// Apollo专属健康检查
router.get('/health/apollo', async (req, res) => {
try {
const start = Date.now();
await apollo.healthCheck();
const latency = Date.now() - start;
res.json({
status: 'ok',
apollo: {
connected: true,
latencyMs: latency,
},
});
} catch (error: any) {
res.status(503).json({
status: 'degraded',
apollo: {
connected: false,
error: error.message,
},
});
}
});
// 就绪检查(适用于Kubernetes)
router.get('/ready', async (req, res) => {
try {
await apollo.healthCheck();
res.json({ ready: true });
} catch {
res.status(503).json({ ready: false });
}
});
export default router;Blue-Green Deployment
蓝绿部署
yaml
undefinedyaml
undefined.github/workflows/blue-green.yml
.github/workflows/blue-green.yml
name: Blue-Green Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Green
run: |
kubectl apply -f k8s/deployment-green.yaml
kubectl rollout status deployment/apollo-service-green
- name: Run smoke tests on Green
run: |
GREEN_URL=$(kubectl get svc apollo-service-green -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl -sf "http://$GREEN_URL/health/apollo" || exit 1
- name: Switch traffic to Green
if: success()
run: |
kubectl patch service apollo-service -p '{"spec":{"selector":{"version":"green"}}}'
- name: Rollback on failure
if: failure()
run: |
kubectl patch service apollo-service -p '{"spec":{"selector":{"version":"blue"}}}'undefinedname: Blue-Green Deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to Green
run: |
kubectl apply -f k8s/deployment-green.yaml
kubectl rollout status deployment/apollo-service-green
- name: Run smoke tests on Green
run: |
GREEN_URL=$(kubectl get svc apollo-service-green -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
curl -sf "http://$GREEN_URL/health/apollo" || exit 1
- name: Switch traffic to Green
if: success()
run: |
kubectl patch service apollo-service -p '{"spec":{"selector":{"version":"green"}}}'
- name: Rollback on failure
if: failure()
run: |
kubectl patch service apollo-service -p '{"spec":{"selector":{"version":"blue"}}}'undefinedDeployment Checklist
部署检查清单
typescript
// scripts/pre-deploy-check.ts
import { apollo } from '../src/lib/apollo/client';
interface Check {
name: string;
check: () => Promise<boolean>;
required: boolean;
}
const checks: Check[] = [
{
name: 'API Key Valid',
check: async () => {
try {
await apollo.healthCheck();
return true;
} catch {
return false;
}
},
required: true,
},
{
name: 'Rate Limit Available',
check: async () => {
// Check we have rate limit headroom
const response = await apollo.searchPeople({ per_page: 1 });
return true; // If we got here, we have capacity
},
required: false,
},
{
name: 'Search Working',
check: async () => {
const result = await apollo.searchPeople({
q_organization_domains: ['apollo.io'],
per_page: 1,
});
return result.people.length > 0;
},
required: true,
},
];
async function runChecks() {
console.log('Running pre-deployment checks...\n');
let allPassed = true;
for (const { name, check, required } of checks) {
try {
const passed = await check();
const status = passed ? 'PASS' : required ? 'FAIL' : 'WARN';
console.log(`[${status}] ${name}`);
if (!passed && required) {
allPassed = false;
}
} catch (error: any) {
console.log(`[FAIL] ${name}: ${error.message}`);
if (required) {
allPassed = false;
}
}
}
if (!allPassed) {
console.error('\nPre-deployment checks failed. Aborting.');
process.exit(1);
}
console.log('\nAll checks passed. Ready to deploy.');
}
runChecks();typescript
// scripts/pre-deploy-check.ts
import { apollo } from '../src/lib/apollo/client';
interface Check {
name: string;
check: () => Promise<boolean>;
required: boolean;
}
const checks: Check[] = [
{
name: 'API Key Valid',
check: async () => {
try {
await apollo.healthCheck();
return true;
} catch {
return false;
}
},
required: true,
},
{
name: 'Rate Limit Available',
check: async () => {
// 检查是否有剩余的速率限制
const response = await apollo.searchPeople({ per_page: 1 });
return true; // 如果执行到这里,说明有可用容量
},
required: false,
},
{
name: 'Search Working',
check: async () => {
const result = await apollo.searchPeople({
q_organization_domains: ['apollo.io'],
per_page: 1,
});
return result.people.length > 0;
},
required: true,
},
];
async function runChecks() {
console.log('Running pre-deployment checks...\n');
let allPassed = true;
for (const { name, check, required } of checks) {
try {
const passed = await check();
const status = passed ? 'PASS' : required ? 'FAIL' : 'WARN';
console.log(`[${status}] ${name}`);
if (!passed && required) {
allPassed = false;
}
} catch (error: any) {
console.log(`[FAIL] ${name}: ${error.message}`);
if (required) {
allPassed = false;
}
}
}
if (!allPassed) {
console.error('\nPre-deployment checks failed. Aborting.');
process.exit(1);
}
console.log('\nAll checks passed. Ready to deploy.');
}
runChecks();Environment Configuration
环境配置
typescript
// src/config/environments.ts
interface EnvironmentConfig {
apollo: {
apiKey: string;
rateLimit: number;
timeout: number;
};
features: {
enrichment: boolean;
sequences: boolean;
};
}
const configs: Record<string, EnvironmentConfig> = {
development: {
apollo: {
apiKey: process.env.APOLLO_API_KEY_DEV!,
rateLimit: 10,
timeout: 30000,
},
features: {
enrichment: true,
sequences: false,
},
},
staging: {
apollo: {
apiKey: process.env.APOLLO_API_KEY_STAGING!,
rateLimit: 50,
timeout: 30000,
},
features: {
enrichment: true,
sequences: true,
},
},
production: {
apollo: {
apiKey: process.env.APOLLO_API_KEY!,
rateLimit: 90,
timeout: 30000,
},
features: {
enrichment: true,
sequences: true,
},
},
};
export function getConfig(): EnvironmentConfig {
const env = process.env.NODE_ENV || 'development';
return configs[env] || configs.development;
}typescript
// src/config/environments.ts
interface EnvironmentConfig {
apollo: {
apiKey: string;
rateLimit: number;
timeout: number;
};
features: {
enrichment: boolean;
sequences: boolean;
};
}
const configs: Record<string, EnvironmentConfig> = {
development: {
apollo: {
apiKey: process.env.APOLLO_API_KEY_DEV!,
rateLimit: 10,
timeout: 30000,
},
features: {
enrichment: true,
sequences: false,
},
},
staging: {
apollo: {
apiKey: process.env.APOLLO_API_KEY_STAGING!,
rateLimit: 50,
timeout: 30000,
},
features: {
enrichment: true,
sequences: true,
},
},
production: {
apollo: {
apiKey: process.env.APOLLO_API_KEY!,
rateLimit: 90,
timeout: 30000,
},
features: {
enrichment: true,
sequences: true,
},
},
};
export function getConfig(): EnvironmentConfig {
const env = process.env.NODE_ENV || 'development';
return configs[env] || configs.development;
}Output
输出内容
- Platform-specific deployment configs (Vercel, GCP, AWS, K8s)
- Health check endpoints
- Blue-green deployment workflow
- Pre-deployment validation
- Environment configuration
- 各平台专属的部署配置(Vercel、GCP、AWS、K8s)
- 健康检查端点
- 蓝绿部署工作流
- 部署前验证
- 环境配置
Error Handling
错误处理
| Issue | Resolution |
|---|---|
| Secret not found | Verify secret configuration |
| Health check fails | Check Apollo connectivity |
| Deployment timeout | Increase timeout, check resources |
| Traffic not switching | Verify service selector |
| 问题 | 解决方法 |
|---|---|
| 密钥未找到 | 验证密钥配置 |
| 健康检查失败 | 检查Apollo连接状态 |
| 部署超时 | 增加超时时间,检查资源配置 |
| 流量未切换 | 验证服务选择器配置 |
Resources
参考资源
Next Steps
下一步
Proceed to for webhook implementation.
apollo-webhooks-events继续查看以实现Webhook功能。
apollo-webhooks-events