feat(deploy): add k3s quickstart overlay

Add self-contained K3s deployment configuration under deploy/k3s/:
- quickstart overlay with PostgreSQL, Redis, backend, frontend, scanner
- Kustomize-based single-command deployment (kubectl apply -k)
- Traefik-compatible Ingress (no nginx ingressClassName)
- Built-in defaults for local testing with skillhub.local
- Remove OAuth2 env vars from backend-deployment to fix empty-client-id crash
This commit is contained in:
River 2026-04-17 18:23:23 +08:00
parent 89bc58d29e
commit f042848671
13 changed files with 909 additions and 0 deletions

234
deploy/k3s/README_zh.md Normal file
View file

@ -0,0 +1,234 @@
# K3s 部署指南
本文档说明如何在 K3s 集群中部署 SkillHub。
## 前置条件
- K3s 集群已就绪(单节点或多节点均可)
- `kubectl` 已配置并能访问集群
- K3s 默认 StorageClass 可用(通常为 `local-path`)
## 目录结构
```
deploy/k3s/
├── README_zh.md
└── overlays/
└── quickstart/ # 一键部署(内置 PostgreSQL + Redis)
├── README.md
├── kustomization.yaml
├── namespace.yaml
├── secret.yaml
├── configmap.yaml
├── services.yaml
├── backend-deployment.yaml
├── frontend-deployment.yaml
├── scanner-deployment.yaml
├── ingress.yaml
├── postgres-statefulset.yaml
└── redis-statefulset.yaml
```
`quickstart` 目录已包含完整部署所需的全部资源文件,无需依赖 `deploy/k8s/` 目录。当前 K3s 部署仅提供该覆盖层,适合快速体验或本地 K3s 环境。生产环境建议在此基础上自行调整 Secret、域名和镜像版本。
## 组件说明
| 组件 | 类型 | 镜像 | 说明 |
|------|------|------|------|
| **skillhub-server** | Deployment | `ghcr.io/iflytek/skillhub-server:latest` | Spring Boot 后端服务,端口 `8080`,profile 为 `docker` |
| **skillhub-web** | Deployment | `ghcr.io/iflytek/skillhub-web:latest` | Nginx 前端服务,端口 `80`,API 上游指向 `skillhub-server:8080` |
| **skillhub-scanner** | Deployment | `ghcr.io/iflytek/skillhub-scanner:latest` | Python 安全扫描器,端口 `8000` |
| **postgres** | StatefulSet | `postgres:16-alpine` | 内置 PostgreSQL 数据库,端口 `5432` |
| **redis** | StatefulSet | `redis:7-alpine` | 内置 Redis,AOF 持久化,端口 `6379` |
## 网络与路由
K3s 默认使用 **Traefik** 作为 Ingress Controller。`quickstart` 配置已移除 `ingressClassName: nginx` 限制,Traefik 会自动接管。
- `/api/*` → `skillhub-server:8080`
- `/*` → `skillhub-web:80`
- 默认域名:`skillhub.local`
- 文件上传大小限制:`100m`
## 存储说明
| PVC | 大小 | 用途 |
|-----|------|------|
| `skillhub-storage-pvc` | 10Gi | 技能包本地存储(挂载到后端 `/var/lib/skillhub/storage`) |
| `postgres-data-0` | 10Gi | PostgreSQL 数据持久化 |
| `redis-data-0` | 5Gi | Redis AOF 数据持久化 |
所有 PVC 均不指定 `storageClassName`,直接采用集群默认 StorageClass(K3s 通常为 `local-path`)。
## 配置说明
### ConfigMap
`quickstart/configmap.yaml` 包含以下关键配置:
| 键 | 默认值 | 说明 |
|---|---|---|
| `redis-host` | `redis` | Redis 主机地址 |
| `redis-port` | `6379` | Redis 端口 |
| `storage-base-path` | `/var/lib/skillhub/storage` | 本地存储挂载路径 |
| `skillhub-storage-provider` | `local` | 存储类型:`local` 或 `s3` |
| `skill-scanner-enabled` | `true` | 是否启用扫描器 |
| `skill-scanner-url` | `http://skillhub-scanner:8000` | 扫描器内部地址 |
| `bootstrap-admin-enabled` | `true` | 是否创建默认管理员 |
| `session-cookie-secure` | `false` | HTTPS 环境请改为 `true` |
### Secret
`quickstart/secret.yaml` 已内置默认 Secret,首次部署无需手动创建。
**注意**:生产环境部署前,务必修改 `secret.yaml` 中的默认值!
| 键 | 默认值 | 说明 |
|---|---|---|
| `spring-datasource-url` | `jdbc:postgresql://postgres:5432/skillhub` | 数据库连接 URL |
| `spring-datasource-username` | `skillhub` | 数据库用户名 |
| `spring-datasource-password` | `skillhub` | 数据库密码 |
| `bootstrap-admin-password` | `ChangeMe!2026` | 默认管理员密码 |
| `oauth2-github-client-id` | `""` | GitHub OAuth ID(可选) |
| `oauth2-github-client-secret` | `""` | GitHub OAuth 密钥(可选) |
| `skill-scanner-llm-api-key` | `""` | LLM API Key(可选) |
| `skill-scanner-llm-model` | `""` | LLM 模型名称(可选) |
## 快速开始
### 一键部署
```bash
kubectl apply -k deploy/k3s/overlays/quickstart/
```
该命令会自动完成:
1. 创建 `skillhub` 命名空间
2. 部署 PostgreSQL 和 Redis(StatefulSet + PVC)
3. 部署后端、前端、扫描器服务
4. 创建 Service、Ingress 和默认 Secret
### 验证部署
```bash
# 查看 Pod 状态
kubectl get pods -n skillhub
# 等待所有 Pod 就绪
kubectl wait --for=condition=ready pod --all -n skillhub --timeout=300s
```
### 访问服务
#### 本地测试(修改 /etc/hosts)
1. 获取 K3s 节点 IP:
```bash
kubectl get nodes -o wide
```
2. 配置本地 hosts:
```bash
echo "<NODE_IP> skillhub.local" | sudo tee -a /etc/hosts
```
3. 浏览器访问:
- **Web UI**: http://skillhub.local
- **API**: http://skillhub.local/api
#### 生产环境
修改 `deploy/k3s/overlays/quickstart/kustomization.yaml` 中的 Ingress host patch:
```yaml
- op: replace
path: /spec/rules/0/host
value: your-domain.com
```
然后重新部署:
```bash
kubectl apply -k deploy/k3s/overlays/quickstart/
```
## 默认管理员
首次启动时,如果 `bootstrap-admin-enabled` 为 `true`,系统会自动创建管理员账户:
- **用户名**: `admin`
- **密码**: `ChangeMe!2026`
**安全建议**:首次登录后请立即修改默认密码;生产环境请务必在部署前修改 `secret.yaml`。
## 生产环境建议
1. **修改 Secret 默认值**:不要直接使用 `quickstart/secret.yaml` 中的默认密码。
2. **锁定镜像版本**:`quickstart/kustomization.yaml` 中默认使用 `latest` tag,建议改为具体的版本号。
3. **存储切换为 S3**:
- 在 ConfigMap 中将 `skillhub-storage-provider` 改为 `s3`
- 在 Secret 中配置 `skillhub-storage-s3-access-key` 和 `skillhub-storage-s3-secret-key`
- 在 `backend-deployment.yaml` 环境变量中补充 `S3_ENDPOINT`、`S3_BUCKET`、`S3_REGION`
4. **启用 HTTPS**:将 `session-cookie-secure` 设为 `true`,并配置 TLS 证书。
5. **使用外部数据库**:对于高可用场景,建议在外部维护 PostgreSQL 和 Redis 集群,并切换到 `external` 模式部署。
## 常见问题
### Pod 一直 Pending
```bash
# 检查 PVC 是否绑定
kubectl get pvc -n skillhub
# 检查 StorageClass
kubectl get storageclass
# 检查节点资源
kubectl describe node <node-name>
```
### 镜像拉取失败
如果镜像是私有的,需要创建拉取凭证:
```bash
kubectl create secret docker-registry ghcr-secret \
--docker-server=ghcr.io \
--docker-username=<GitHub用户名> \
--docker-password=<GitHub Token> \
-n skillhub
```
然后在 Deployment 的 `imagePullSecrets` 中引用该 Secret。
### 数据库连接失败
```bash
# 检查 PostgreSQL 是否就绪
kubectl logs postgres-0 -n skillhub
# 检查 Secret 配置
kubectl get secret skillhub-secret -n skillhub -o yaml
```
### 查看日志
```bash
# 后端日志
kubectl logs -l app.kubernetes.io/name=skillhub-server -n skillhub -f
# 前端日志
kubectl logs -l app.kubernetes.io/name=skillhub-web -n skillhub -f
# 扫描器日志
kubectl logs -l app.kubernetes.io/name=skillhub-scanner -n skillhub -f
```
## 清理
```bash
# 删除所有资源
kubectl delete -k deploy/k3s/overlays/quickstart/
# 删除命名空间
kubectl delete namespace skillhub
```

View file

@ -0,0 +1,94 @@
# K3s 一键部署(Quick Start)
基于 Kustomize 的 K3s 快速部署配置,内置 PostgreSQL + Redis,一条命令即可完成部署。
## 前置条件
- 可用的 K3s 集群(单节点或多节点均可)
- `kubectl` 已配置并能访问集群
- K3s 集群默认 StorageClass 可用(通常为 `local-path`)
## 部署
```bash
kubectl apply -k deploy/k3s/overlays/quickstart/
```
该命令会自动完成:
1. 创建 `skillhub` 命名空间
2. 部署 PostgreSQL 和 Redis(StatefulSet + PVC)
3. 部署后端、前端、扫描器服务
4. 创建 Service、Ingress 和默认 Secret
## 验证
```bash
# 查看 Pod 状态
kubectl get pods -n skillhub
# 等待所有 Pod 就绪
kubectl wait --for=condition=ready pod --all -n skillhub --timeout=300s
```
## 访问
K3s 默认使用 **Traefik** 作为 Ingress Controller,此配置已移除 `nginx` 的 `ingressClassName` 限制。
### 本地测试(NodePort / HostPort 场景)
1. 获取 Ingress 暴露的 IP:
```bash
kubectl get ingress skillhub -n skillhub
```
2. 配置本地 hosts(将 `<NODE_IP>` 替换为实际节点 IP):
```bash
echo "<NODE_IP> skillhub.local" | sudo tee -a /etc/hosts
```
3. 浏览器访问:
- **Web UI**: http://skillhub.local
- **API**: http://skillhub.local/api
### 生产环境
修改 `kustomization.yaml` 中的 Ingress host patch,将 `skillhub.local` 替换为你的真实域名:
```yaml
- op: replace
path: /spec/rules/0/host
value: your-domain.com
```
然后重新执行:
```bash
kubectl apply -k deploy/k3s/overlays/quickstart/
```
## 默认管理员
首次启动会自动创建管理员账户:
- **用户名**: `admin`
- **密码**: `ChangeMe!2026`(配置在 `secret.yaml` 中)
**安全建议**:首次登录后请立即修改默认密码;生产环境部署前务必修改 `secret.yaml` 中的默认值。
## 存储说明
| PVC | 大小 | 说明 |
|-----|------|------|
| `skillhub-storage-pvc` | 10Gi | 技能文件本地存储 |
| `postgres-data-0` | 10Gi | PostgreSQL 数据 |
| `redis-data-0` | 5Gi | Redis AOF 持久化 |
## 清理
```bash
kubectl delete -k deploy/k3s/overlays/quickstart/
```
如需同时删除命名空间:
```bash
kubectl delete namespace skillhub
```

View file

@ -0,0 +1,146 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: skillhub-server
labels:
app.kubernetes.io/name: skillhub-server
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: skillhub-server
template:
metadata:
labels:
app.kubernetes.io/name: skillhub-server
spec:
containers:
- name: server
image: ghcr.io/iflytek/skillhub-server:edge
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
name: http
env:
- name: SPRING_PROFILES_ACTIVE
value: docker
# Database
- name: SPRING_DATASOURCE_URL
valueFrom:
secretKeyRef:
name: skillhub-secret
key: spring-datasource-url
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: skillhub-secret
key: spring-datasource-username
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: skillhub-secret
key: spring-datasource-password
# Redis
- name: SPRING_DATA_REDIS_HOST
valueFrom:
configMapKeyRef:
name: skillhub-config
key: redis-host
- name: SPRING_DATA_REDIS_PORT
valueFrom:
configMapKeyRef:
name: skillhub-config
key: redis-port
# Storage
- name: STORAGE_BASE_PATH
valueFrom:
configMapKeyRef:
name: skillhub-config
key: storage-base-path
- name: SKILLHUB_STORAGE_PROVIDER
valueFrom:
configMapKeyRef:
name: skillhub-config
key: skillhub-storage-provider
# Scanner
- name: SKILLHUB_SECURITY_SCANNER_ENABLED
valueFrom:
configMapKeyRef:
name: skillhub-config
key: skill-scanner-enabled
- name: SKILLHUB_SECURITY_SCANNER_URL
valueFrom:
configMapKeyRef:
name: skillhub-config
key: skill-scanner-url
- name: SKILLHUB_SECURITY_SCANNER_MODE
valueFrom:
configMapKeyRef:
name: skillhub-config
key: skill-scanner-mode
# Session
- name: SESSION_COOKIE_SECURE
valueFrom:
configMapKeyRef:
name: skillhub-config
key: session-cookie-secure
# Bootstrap Admin (non-sensitive from ConfigMap)
- name: BOOTSTRAP_ADMIN_ENABLED
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-enabled
- name: BOOTSTRAP_ADMIN_USER_ID
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-user-id
- name: BOOTSTRAP_ADMIN_USERNAME
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-username
- name: BOOTSTRAP_ADMIN_DISPLAY_NAME
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-display-name
- name: BOOTSTRAP_ADMIN_EMAIL
valueFrom:
configMapKeyRef:
name: skillhub-config
key: bootstrap-admin-email
# Bootstrap Admin Password (sensitive from Secret)
- name: BOOTSTRAP_ADMIN_PASSWORD
valueFrom:
secretKeyRef:
name: skillhub-secret
key: bootstrap-admin-password
optional: true
volumeMounts:
- name: skillhub-storage
mountPath: /var/lib/skillhub/storage
readinessProbe:
httpGet:
path: /actuator/health
port: http
initialDelaySeconds: 20
periodSeconds: 10
livenessProbe:
httpGet:
path: /actuator/health
port: http
initialDelaySeconds: 30
periodSeconds: 15
volumes:
- name: skillhub-storage
persistentVolumeClaim:
claimName: skillhub-storage-pvc

View file

@ -0,0 +1,44 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: skillhub-config
data:
# Redis 配置
# 使用外部 Redis:修改为外部主机地址
# 使用内置 Redis(overlays/with-infra):保持 redis
redis-host: redis
redis-port: "6379"
# 技能存储路径
storage-base-path: /var/lib/skillhub/storage
# 存储配置
# local: 本地存储(默认), s3: S3/OSS 对象存储
skillhub-storage-provider: local
# 技能扫描器配置
skill-scanner-enabled: "true"
skill-scanner-url: http://skillhub-scanner:8000
skill-scanner-mode: upload
# Bootstrap 管理员配置(非敏感)
bootstrap-admin-enabled: "true"
bootstrap-admin-user-id: docker-admin
bootstrap-admin-username: admin
bootstrap-admin-display-name: Platform Admin
bootstrap-admin-email: admin@example.com
# Session 配置
# HTTP 环境设为 false,HTTPS 环境设为 true
session-cookie-secure: "false"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: skillhub-storage-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi

View file

@ -0,0 +1,38 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: skillhub-web
labels:
app.kubernetes.io/name: skillhub-web
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: skillhub-web
template:
metadata:
labels:
app.kubernetes.io/name: skillhub-web
spec:
containers:
- name: web
image: ghcr.io/iflytek/skillhub-web:edge
imagePullPolicy: IfNotPresent
env:
- name: SKILLHUB_API_UPSTREAM
value: http://skillhub-server:8080
ports:
- containerPort: 80
name: http
readinessProbe:
httpGet:
path: /nginx-health
port: http
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /nginx-health
port: http
initialDelaySeconds: 10
periodSeconds: 15

View file

@ -0,0 +1,26 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: skillhub
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: 100m
spec:
ingressClassName: nginx
rules:
- host: skills.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: skillhub-server
port:
number: 8080
- path: /
pathType: Prefix
backend:
service:
name: skillhub-web
port:
number: 80

View file

@ -0,0 +1,47 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: skillhub
resources:
- namespace.yaml
- postgres-statefulset.yaml
- redis-statefulset.yaml
- configmap.yaml
- services.yaml
- backend-deployment.yaml
- frontend-deployment.yaml
- scanner-deployment.yaml
- ingress.yaml
- secret.yaml
images:
- name: ghcr.io/iflytek/skillhub-server
newTag: latest
- name: ghcr.io/iflytek/skillhub-web
newTag: latest
- name: ghcr.io/iflytek/skillhub-scanner
newTag: latest
patches:
# 移除 nginx ingressClassName,适配 k3s 默认 Traefik
- target:
kind: Ingress
name: skillhub
patch: |
- op: remove
path: /spec/ingressClassName
# 修改默认域名为 skillhub.local,方便本地 /etc/hosts 测试
- target:
kind: Ingress
name: skillhub
patch: |
- op: replace
path: /spec/rules/0/host
value: skillhub.local
labels:
- pairs:
app.kubernetes.io/part-of: skillhub
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/deployment: k3s-quickstart

View file

@ -0,0 +1,4 @@
apiVersion: v1
kind: Namespace
metadata:
name: skillhub

View file

@ -0,0 +1,86 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
labels:
app.kubernetes.io/name: postgres
spec:
serviceName: postgres
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: postgres
template:
metadata:
labels:
app.kubernetes.io/name: postgres
spec:
containers:
- name: postgres
image: postgres:16-alpine
ports:
- containerPort: 5432
name: postgres
env:
- name: POSTGRES_DB
value: skillhub
- name: POSTGRES_USER
valueFrom:
secretKeyRef:
name: skillhub-secret
key: spring-datasource-username
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: skillhub-secret
key: spring-datasource-password
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
readinessProbe:
exec:
command:
- pg_isready
- -U
- skillhub
initialDelaySeconds: 10
periodSeconds: 10
livenessProbe:
exec:
command:
- pg_isready
- -U
- skillhub
initialDelaySeconds: 30
periodSeconds: 15
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
---
apiVersion: v1
kind: Service
metadata:
name: postgres
labels:
app.kubernetes.io/name: postgres
spec:
type: ClusterIP
ports:
- port: 5432
targetPort: postgres
name: postgres
selector:
app.kubernetes.io/name: postgres

View file

@ -0,0 +1,75 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
labels:
app.kubernetes.io/name: redis
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: redis
template:
metadata:
labels:
app.kubernetes.io/name: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
name: redis
command:
- redis-server
- --appendonly
- "yes"
volumeMounts:
- name: redis-data
mountPath: /data
readinessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 10
periodSeconds: 15
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
---
apiVersion: v1
kind: Service
metadata:
name: redis
labels:
app.kubernetes.io/name: redis
spec:
type: ClusterIP
ports:
- port: 6379
targetPort: redis
name: redis
selector:
app.kubernetes.io/name: redis

View file

@ -0,0 +1,48 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: skillhub-scanner
labels:
app.kubernetes.io/name: skillhub-scanner
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: skillhub-scanner
template:
metadata:
labels:
app.kubernetes.io/name: skillhub-scanner
spec:
containers:
- name: scanner
image: ghcr.io/iflytek/skillhub-scanner:edge
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8000
name: http
env:
- name: SKILL_SCANNER_LLM_API_KEY
valueFrom:
secretKeyRef:
name: skillhub-secret
key: skill-scanner-llm-api-key
optional: true
- name: SKILL_SCANNER_LLM_MODEL
valueFrom:
secretKeyRef:
name: skillhub-secret
key: skill-scanner-llm-model
optional: true
readinessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 20
periodSeconds: 15

View file

@ -0,0 +1,26 @@
apiVersion: v1
kind: Secret
metadata:
name: skillhub-secret
namespace: skillhub
type: Opaque
stringData:
# PostgreSQL 连接配置(使用内置数据库)
spring-datasource-url: jdbc:postgresql://postgres:5432/skillhub
spring-datasource-username: skillhub
spring-datasource-password: skillhub
# Bootstrap 管理员密码(首次登录后请修改)
bootstrap-admin-password: ChangeMe!2026
# GitHub OAuth(可选)
oauth2-github-client-id: ""
oauth2-github-client-secret: ""
# LLM 配置(可选,用于技能扫描)
skill-scanner-llm-api-key: ""
skill-scanner-llm-model: ""
# S3 存储配置(可选)
skillhub-storage-s3-access-key: ""
skillhub-storage-s3-secret-key: ""

View file

@ -0,0 +1,41 @@
apiVersion: v1
kind: Service
metadata:
name: skillhub-server
labels:
app.kubernetes.io/name: skillhub-server
spec:
selector:
app.kubernetes.io/name: skillhub-server
ports:
- name: http
port: 8080
targetPort: http
---
apiVersion: v1
kind: Service
metadata:
name: skillhub-scanner
labels:
app.kubernetes.io/name: skillhub-scanner
spec:
selector:
app.kubernetes.io/name: skillhub-scanner
ports:
- name: http
port: 8000
targetPort: http
---
apiVersion: v1
kind: Service
metadata:
name: skillhub-web
labels:
app.kubernetes.io/name: skillhub-web
spec:
selector:
app.kubernetes.io/name: skillhub-web
ports:
- name: http
port: 80
targetPort: http