diff --git a/docs/kubernetes/README.md b/docs/kubernetes/README.md index df4704a390..cc421f569b 100644 --- a/docs/kubernetes/README.md +++ b/docs/kubernetes/README.md @@ -2,7 +2,10 @@ 本目录提供从零到一的 Kubernetes 集群安装与常用脚本。建议:先阅读本 README 的概览与快速开始,再按需查看详细版文档。 -- 详细版安装手册:见 `k8s-installtion.md`(分步说明、完整命令与排错) +### 文档索引 + +- **Kubernetes 安装**:`k8s-installtion.md`(分步说明、完整命令与排错) +- **Istio 配置**:`istio-hostnetwork-notes.md`(将 Istio IngressGateway 切换为 hostNetwork 模式指南) ### 快速开始 @@ -52,8 +55,33 @@ kubectl get pods -A - 无法拉取镜像:检查网络/镜像源,可用 `k8s-image-pull-and-import.sh` 预拉取。 - `kubectl` 连接异常:确认 `$HOME/.kube/config` 配置与权限。 -### 与 Istio 的关系 +### Istio 服务网格配置 -本目录仅负责 Kubernetes 底座与 CNI。若使用 Istio 网关与 VirtualService,请在上层项目文档按步骤部署 Istio,并确认 `istio-ingressgateway` 可达。 +本目录的 Kubernetes 集群安装完成后,如需使用 Istio 作为服务网格和入口网关,请参考: + +#### Istio hostNetwork 模式配置 + +**适用场景**: +- 只有 master 节点有公网 IP +- 需要 Istio IngressGateway 替代 nginx-ingress-controller +- 需要 Istio 直接监听宿主机的 80/443 端口 + +**详细指南**:请参阅 [`istio-hostnetwork-notes.md`](./istio-hostnetwork-notes.md) + +**快速概览**: +1. 安装 Istio(使用 `istioctl install` 或 Helm) +2. 按照指南将 `istio-ingressgateway` 切换为 hostNetwork 模式 +3. 配置 Gateway 和 VirtualService 进行流量路由 +4. 配置 TLS 证书 Secret + +**注意事项**: +- 迁移前确保停止 nginx 或其他占用 80/443 的服务 +- 需要将 TLS 证书 Secret 复制到 `istio-system` 命名空间 +- hostNetwork 模式下,Service 类型可以是 `ClusterIP` 或 `LoadBalancer` + +#### 其他 Istio 文档 + +- Istio 官方文档:https://istio.io/latest/docs/ +- Istio 安装指南:https://istio.io/latest/docs/setup/install/ diff --git a/docs/kubernetes/istio-hostnetwork-notes.md b/docs/kubernetes/istio-hostnetwork-notes.md new file mode 100644 index 0000000000..0a9d09b136 --- /dev/null +++ b/docs/kubernetes/istio-hostnetwork-notes.md @@ -0,0 +1,454 @@ +# Istio IngressGateway 切换为 hostNetwork 模式指南 + +## 概述 + +本指南适用于以下场景: +- 只有 master 节点有公网 IP +- 需要 Istio IngressGateway 替代 nginx-ingress-controller +- 需要 Istio 直接监听宿主机的 80/443 端口 + +### 为什么选择 hostNetwork? + +1. **公网 IP 限制**:只有 master 节点有公网 IP,流量入口必须在 master +2. **端口一致性**:需要监听标准端口 80/443,与 nginx 保持一致 +3. **无缝迁移**:无需修改 DNS 或负载均衡器配置 + +## 安装 Istio 1.27.1 + +### 1. 下载 istioctl + +```bash +# 下载 Istio 1.27.1 +# 根据系统架构选择:x86_64 或 arm64 +curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.27.1 TARGET_ARCH=x86_64 sh - + +# 进入目录 +cd istio-1.27.1 + +# 临时添加到 PATH(当前会话有效) +export PATH=$PWD/bin:$PATH + +# 或永久安装到系统路径 +sudo cp bin/istioctl /usr/local/bin/ +sudo chmod +x /usr/local/bin/istioctl + +# 验证安装 +istioctl version +``` + +**说明**: +- `TARGET_ARCH` 根据系统架构选择:`x86_64`(Intel/AMD)或 `arm64`(ARM) +- 如果使用临时 PATH,每次新终端会话都需要重新设置 +- 推荐将 `istioctl` 复制到 `/usr/local/bin` 以便全局使用 + +### 2. 安装 Istio + +使用 `default` profile 安装 Istio: + +```bash +# 安装 Istio(使用 default profile) +istioctl install --set profile=default -y + +# 验证安装 +kubectl get pods -n istio-system +kubectl get svc -n istio-system +``` + +**预期输出**: +- `istiod` Pod 应该处于 `Running` 状态 +- `istio-ingressgateway` Pod 应该处于 `Running` 状态 +- `istio-egressgateway` Pod 应该处于 `Running` 状态(可选) + +### 3. 验证安装 + +```bash +# 检查 Istio 组件状态 +istioctl verify-install + +# 查看 Istio 版本 +istioctl version + +# 检查所有命名空间的 Istio 资源 +kubectl get crd | grep istio +``` + + +### 4. 卸载 Istio(如需要) + +如果需要卸载 Istio: + +```bash +# 卸载 Istio +istioctl uninstall --purge -y + +# 删除命名空间 +kubectl delete namespace istio-system + +# 删除 CRD(可选,会删除所有 Istio 配置) +kubectl get crd | grep istio | awk '{print $1}' | xargs kubectl delete crd +``` + +## 前置检查 + +**注意**:如果尚未安装 Istio,请先完成上述"安装 Istio 1.27.1"章节的步骤。 + +### 1. 确认集群状态 + +```bash +# 检查节点 +kubectl get nodes + +# 检查 Istio 组件(如果已安装) +kubectl get pods -n istio-system + +# 检查当前 Service 配置(如果已安装) +kubectl get svc istio-ingressgateway -n istio-system + +# 检查 Deployment 配置(如果已安装) +kubectl get deploy istio-ingressgateway -n istio-system -o yaml | head -n 50 +``` + +### 2. 释放端口(避免冲突) + +**k3s 环境**: +- 如有 traefik,需要停止或释放 80/443 +- 检查是否有其他服务占用端口:`ss -tlnp | grep -E ':(80|443) '` + +**标准 Kubernetes 环境**: +```bash +# 停止 nginx-ingress-controller(如果存在) +kubectl scale deployment my-release-nginx-ingress-controller \ + -n nginx-ingress-controller --replicas=0 + +# 验证端口已释放 +ss -tlnp | grep -E ':(80|443) ' || echo "80/443 not listening" +``` + +## 完整操作步骤 + +### 步骤 1:调整 Service(可选) + +如果后续需要接真实 LB,可保留 `LoadBalancer` 类型;为便于本地测试,可先改为 `ClusterIP`: + +```bash +# 修改 Service 类型为 ClusterIP +kubectl patch svc istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"replace","path":"/spec/type","value":"ClusterIP"}]' + +# 调整端口映射(直通 80/443/15021) +kubectl patch svc istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"replace","path":"/spec/ports","value":[ + {"name":"http","port":80,"targetPort":80,"protocol":"TCP"}, + {"name":"https","port":443,"targetPort":443,"protocol":"TCP"}, + {"name":"status-port","port":15021,"targetPort":15021,"protocol":"TCP"}]}]' +``` + +### 步骤 2:启用 hostNetwork 模式 + +```bash +# 1. 启用 hostNetwork +kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/hostNetwork","value":true}]' + +# 2. 设置 DNS 策略 +kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/dnsPolicy","value":"ClusterFirstWithHostNet"}]' + +# 3. 绑定到 master 节点(根据实际节点名调整) +kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/nodeSelector","value":{"kubernetes.io/hostname":"master"}}]' + +# 4. 添加容忍(如果 master 节点有 control-plane taint) +kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/tolerations","value":[{"key":"node-role.kubernetes.io/control-plane","operator":"Exists","effect":"NoSchedule"}]}]' +``` + +### 步骤 3:配置容器端口 + +```bash +# 让容器直接监听宿主机的 80/443/15021 +kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"replace","path":"/spec/template/spec/containers/0/ports","value":[ + {"containerPort":80,"hostPort":80,"protocol":"TCP","name":"http"}, + {"containerPort":443,"hostPort":443,"protocol":"TCP","name":"https"}, + {"containerPort":15021,"hostPort":15021,"protocol":"TCP","name":"status-port"}, + {"containerPort":15090,"protocol":"TCP","name":"http-envoy-prom"}]}]' +``` + +### 步骤 4:配置安全上下文(解决权限问题) + +```bash +# 1. 添加 NET_BIND_SERVICE 能力 +kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"add","path":"/spec/template/spec/containers/0/securityContext/capabilities/add","value":["NET_BIND_SERVICE"]}]' + +# 2. 以 root 身份运行(允许绑定特权端口) +kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"replace","path":"/spec/template/spec/securityContext/runAsNonRoot","value":false},\ + {"op":"replace","path":"/spec/template/spec/securityContext/runAsUser","value":0},\ + {"op":"replace","path":"/spec/template/spec/securityContext/runAsGroup","value":0}]' + +# 3. 设置环境变量(告知 Istio 这是特权 Pod) +kubectl set env deployment/istio-ingressgateway -n istio-system ISTIO_META_UNPRIVILEGED_POD=false +``` + +### 步骤 5:重启 Deployment + +```bash +# 先缩容到 0,避免 hostPort 冲突 +kubectl scale deployment istio-ingressgateway -n istio-system --replicas=0 + +# 等待 Pod 完全终止 +kubectl rollout status deployment/istio-ingressgateway -n istio-system --timeout=60s || true +sleep 3 + +# 扩容到 1 +kubectl scale deployment istio-ingressgateway -n istio-system --replicas=1 + +# 等待新 Pod 就绪 +kubectl rollout status deployment/istio-ingressgateway -n istio-system --timeout=120s +``` + +## 验证配置 + +### 1. 检查 Pod 状态 + +```bash +# 查看 Pod 状态和 IP(hostNetwork 模式下 IP 应为节点 IP) +kubectl get pods -n istio-system -o wide + +# 确认 hostNetwork 已启用 +kubectl get pod -n istio-system -l app=istio-ingressgateway \ + -o jsonpath='{.items[0].spec.hostNetwork}' +# 应该输出: true +``` + +### 2. 检查端口监听 + +```bash +# 在 master 节点上检查端口监听 +ss -tlnp | grep -E ':(80|443|15021) ' + +# 或在 Pod 内部检查 +kubectl exec -n istio-system deploy/istio-ingressgateway -- \ + ss -tlnp | grep -E ':(80|443|15021) ' +``` + +### 3. 检查 Istio 配置 + +```bash +# 查看 Envoy listener 配置 +istioctl proxy-config listener deploy/istio-ingressgateway.istio-system + +# 检查配置分析 +istioctl analyze -A +``` + +## 配置 Gateway 和 VirtualService + +### 1. 准备 TLS 证书 Secret + +如果证书 Secret 在其他命名空间,需要复制到 `istio-system`: + +```bash +# 复制 Secret(示例) +kubectl get secret -n -o yaml | \ + sed "s/namespace: /namespace: istio-system/" | \ + kubectl apply -f - + +# 验证 +kubectl get secret -n istio-system +``` + +**注意**:证书文件(`.crt`)如果包含多个 `BEGIN CERTIFICATE` 块是正常的,这是证书链(服务器证书 + 中间证书)。Kubernetes Secret 和 Istio Gateway 都支持这种格式。 + +### 2. 创建 Gateway + +```yaml +apiVersion: networking.istio.io/v1beta1 +kind: Gateway +metadata: + name: devstar-gateway + namespace: istio-system +spec: + selector: + istio: ingressgateway + servers: + - port: + number: 80 + name: http + protocol: HTTP + hosts: + - devstar.cn + - www.devstar.cn + - port: + number: 443 + name: https + protocol: HTTPS + tls: + mode: SIMPLE + credentialName: devstar-studio-tls-secret-devstar-cn + hosts: + - devstar.cn + - www.devstar.cn +``` + +### 3. 创建 VirtualService + +```yaml +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: devstar-studio-gitea + namespace: devstar-studio-ns +spec: + hosts: + - devstar.cn + - www.devstar.cn + gateways: + - istio-system/devstar-gateway + http: + # www.devstar.cn 重定向到 devstar.cn (308 永久重定向) + - match: + - headers: + host: + exact: www.devstar.cn + redirect: + authority: devstar.cn + redirectCode: 308 + # devstar.cn 路由到后端服务 + - match: + - uri: + prefix: / + route: + - destination: + host: devstar-studio-gitea-http + port: + number: 3000 +``` + +### 4. 验证 Gateway 和 VirtualService + +```bash +# 检查 Gateway +kubectl get gateway -n istio-system + +# 检查 VirtualService +kubectl get virtualservice -A + +# 查看详细配置 +kubectl describe gateway devstar-gateway -n istio-system +kubectl describe virtualservice devstar-studio-gitea -n devstar-studio-ns +``` + +## 测试访问 + +```bash +# HTTP 测试 +curl -H "Host: devstar.cn" http:// -I + +# HTTPS 测试 +curl -k --resolve devstar.cn:443: https://devstar.cn -I + +# 测试重定向(www.devstar.cn -> devstar.cn) +curl -I -H "Host: www.devstar.cn" http:// +# 应该返回: HTTP/1.1 308 Permanent Redirect +``` + +## 启用服务网格(可选) + +如果需要为其他命名空间启用自动 sidecar 注入: + +```bash +# 为命名空间启用自动注入 +kubectl label namespace istio-injection=enabled + +# 验证 +kubectl get namespace -L istio-injection + +# 重启现有 Pod 以注入 sidecar +kubectl rollout restart deployment -n +``` + +## 常见问题 + +### 1. Pod 一直 Pending + +**原因**:旧 Pod 仍占用 hostPort,新 Pod 无法调度。 + +**解决**: +```bash +# 手动删除旧 Pod +kubectl delete pod -n istio-system -l app=istio-ingressgateway + +# 或先缩容再扩容 +kubectl scale deployment istio-ingressgateway -n istio-system --replicas=0 +kubectl scale deployment istio-ingressgateway -n istio-system --replicas=1 +``` + +### 2. Envoy 报 "Permission denied" 无法绑定 80/443 + +**原因**:容器没有足够权限绑定特权端口。 + +**解决**: +- 确认已添加 `NET_BIND_SERVICE` capability +- 确认 `runAsUser: 0` 和 `runAsNonRoot: false` +- 确认 `ISTIO_META_UNPRIVILEGED_POD=false` + +### 3. Istiod 日志显示 "skipping privileged gateway port" + +**原因**:Istio 认为 Pod 是无特权模式。 + +**解决**: +```bash +kubectl set env deployment/istio-ingressgateway -n istio-system ISTIO_META_UNPRIVILEGED_POD=false +kubectl rollout restart deployment istio-ingressgateway -n istio-system +``` + +### 4. Gateway 冲突(IST0145) + +**原因**:多个 Gateway 使用相同的 selector 和端口,但 hosts 冲突。 + +**解决**: +- 合并多个 Gateway 到一个,在 `hosts` 中列出所有域名 +- 或确保不同 Gateway 的 `hosts` 不重叠 + +## 回滚方案 + +如果需要回滚到默认配置: + +```bash +# 1. 恢复 nginx(如果之前使用) +kubectl scale deployment my-release-nginx-ingress-controller \ + -n nginx-ingress-controller --replicas=1 + +# 2. 恢复 Istio 为默认配置 +istioctl install --set profile=default -y + +# 3. 或手动删除 hostNetwork 相关配置 +kubectl patch deployment istio-ingressgateway -n istio-system --type='json' \ + -p='[{"op":"remove","path":"/spec/template/spec/hostNetwork"}]' +``` + +## 端口映射说明 + +### Istio 默认端口配置 + +- **容器内部端口**:Istio 默认让 Envoy 监听 8080(HTTP)和 8443(HTTPS) +- **Service 端口映射**:Service 的 80 端口映射到容器的 8080(targetPort: 8080),443 映射到 8443 +- **为什么不是 80/443**:这是 Istio 的设计,避免与主机上的其他服务冲突 + +### hostNetwork 模式下的端口配置 + +使用 hostNetwork 模式时: +- 容器直接使用主机网络,需要监听主机的 80/443 端口 +- 因此需要修改容器端口配置,让容器监听 80/443 而不是 8080/8443 +- 同时需要配置 IstioOperator 的 values,让 Envoy 实际监听 80/443 + +## 注意事项 + +1. **端口冲突**:迁移前确保停止 nginx 或其他占用 80/443 的服务 +2. **Sidecar 资源**:每个 Pod 会增加 ~100MB 内存和 ~100m CPU +3. **TLS 证书**:需要将证书 Secret 复制到 istio-system 命名空间,或通过 Gateway 配置指定命名空间 +4. **性能影响**:sidecar 会增加少量延迟(通常 <1ms) +5. **Service 类型**:hostNetwork 模式下,Service 类型可以是 `ClusterIP` 或 `LoadBalancer`,不影响功能