添加了istio相关说明

This commit is contained in:
panshuxiao
2025-11-16 19:02:20 +08:00
repo.diff.parent 4a0b04af17
repo.diff.commit a65e368522
repo.diff.stats_desc%!(EXTRA int=2, int=485, int=3)

repo.diff.view_file

@@ -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/

repo.diff.view_file

@@ -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 状态和 IPhostNetwork 模式下 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 <your-tls-secret> -n <source-namespace> -o yaml | \
sed "s/namespace: <source-namespace>/namespace: istio-system/" | \
kubectl apply -f -
# 验证
kubectl get secret <your-tls-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://<master-ip> -I
# HTTPS 测试
curl -k --resolve devstar.cn:443:<master-ip> https://devstar.cn -I
# 测试重定向www.devstar.cn -> devstar.cn
curl -I -H "Host: www.devstar.cn" http://<master-ip>
# 应该返回: HTTP/1.1 308 Permanent Redirect
```
## 启用服务网格(可选)
如果需要为其他命名空间启用自动 sidecar 注入:
```bash
# 为命名空间启用自动注入
kubectl label namespace <namespace> istio-injection=enabled
# 验证
kubectl get namespace -L istio-injection
# 重启现有 Pod 以注入 sidecar
kubectl rollout restart deployment -n <namespace>
```
## 常见问题
### 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 监听 8080HTTP和 8443HTTPS
- **Service 端口映射**Service 的 80 端口映射到容器的 8080targetPort: 8080443 映射到 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`,不影响功能