一、什么是微服务
在 Kubernetes 中,微服务是一种将应用拆分为独立、可扩展的小型服务的架构模式。每个微服务通常运行在独立的容器中,并通过网络进行通信。Kubernetes 提供了多种机制来管理和暴露这些微服务,使其能够高效地运行和扩展。
1.1 服务暴露与 Service
在 Kubernetes 中,Service 是一种抽象资源,它将一组提供相同服务的 Pod 组合在一起(使用 标签选择器(Labels Selector) 来动态关联后端的 Pod。标签选择器定义了哪些 Pod 属于这个 Service),并为它们提供一个统一的访问接口。这个接口可以是一个虚拟 IP 地址、一个 DNS 名称或一个固定的端口,使得客户端可以方便地访问服务,而无需关心后端 Pod 的具体实现细节。Service 的主要功能包括:
-
服务发现:通过 DNS 或环境变量,Pod 可以发现并连接到其他服务。
-
负载均衡:Service 会自动将请求分发到后端的 Pod 上,实现负载均衡。
-
默认支持 4 层负载均衡:Service 默认支持 TCP/UDP 等传输层协议。如果需要 7 层功能(如 HTTP/HTTPS 路由),可以通过 Ingress 来实现。
1.2 Service 的类型
Kubernetes 提供了多种类型的 Service,每种类型适用于不同的场景:
类型 | 作用描述 |
---|---|
ClusterIP | 默认类型,Kubernetes 系统自动分配一个虚拟 IP,仅在集群内部可访问。 |
NodePort | 将 Service 暴露为每个节点上的一个端口,外部可通过节点 IP 加端口访问。 |
LoadBalancer | 在 NodePort 的基础上,通过云服务提供商创建外部负载均衡器,适用于云环境。 |
ExternalName | 将服务通过 DNS CNAME 记录转发到指定的外部域名。 |
1.3 示例:创建一个 Service
以下是一个简单的 Service 示例,将一个 Deployment 暴露为一个 ClusterIP 类型的 Service:
# 创建 Deployment
kubectl create deployment admin --image myapp:v1 --replicas 2 --dry-run=client -o yaml > admin.yaml
# 创建 Service
kubectl expose deployment admin --port 80 --target-port 80 --dry-run=client -o yaml >> admin.yaml
# 查看 Service
kubectl get services
二、微服务的类型详解
2.1 ClusterIP
ClusterIP 是默认的 Service 类型,它会分配一个虚拟 IP,仅在集群内部可访问。这种类型的 Service 适用于仅在集群内部通信的场景。
特点:
-
内部访问:仅在集群内部可访问。
-
自动发现:集群内的 Pod 可以通过 DNS 或环境变量发现其他 Service。
-
负载均衡:自动将请求分发到后端的 Pod。
示例:
apiVersion: v1 # 指定 Kubernetes API 版本
kind: Service # 资源类型为 Service
metadata: # 元数据部分name: admin # Service 的名称
spec: # Service 的具体配置ports: # 定义 Service 的端口配置- port: 80 # Service 的端口号targetPort: 80 # 后端 Pod 的目标端口号selector: # 用于选择后端 Pod 的标签选择器app: admin # 匹配标签为 app=admin 的 Podtype: ClusterIP # Service 类型为 ClusterIP
2.2 Headless Service
Headless Service 是一种特殊的 ClusterIP 类型,它不会分配 Cluster IP,kube-proxy 也不会处理它。这种类型的 Service 通常用于直接访问 Pod 的 IP 地址,适用于需要直接与 Pod 通信的场景。
示例:
apiVersion: v1 # 指定 Kubernetes API 版本
kind: Service # 资源类型为 Service
metadata: # 元数据部分name: admin # Service 的名称
spec: # Service 的具体配置ports: # 定义 Service 的端口配置- port: 80 # Service 的端口号targetPort: 80 # 后端 Pod 的目标端口号selector: # 用于选择后端 Pod 的标签选择器app: admin # 匹配标签为 app=admin 的 Podtype: ClusterIP # Service 类型为 ClusterIPclusterIP: None # 设置为 None,表示不分配 Cluster IP
2.3 NodePort
NodePort 类型的 Service 会在每个节点上绑定一个端口,外部可以通过节点 IP 加端口的方式访问 Service。
特点:
-
外部访问:可以通过节点 IP 加端口的方式访问。
-
端口范围:默认端口范围为 30000-32767,可以通过修改 kube-apiserver 配置来扩展范围。
示例:
apiVersion: v1 # 指定 Kubernetes API 版本
kind: Service # 资源类型为 Service
metadata: # 元数据部分name: admin # Service 的名称
spec: # Service 的具体配置ports: # 定义 Service 的端口配置- port: 80 # Service 的端口号targetPort: 80 # 后端 Pod 的目标端口号nodePort: 31771 # 在每个节点上绑定的端口号selector: # 用于选择后端 Pod 的标签选择器app: admin # 匹配标签为 app=admin 的 Podtype: NodePort # Service 类型为 NodePort
2.4 LoadBalancer
LoadBalancer 类型的 Service 通过云服务提供商的负载均衡器实现外部访问。它适用于云环境,不支持裸金属环境。
特点:
-
外部负载均衡:通过云服务提供商的负载均衡器实现。
-
自动分配 VIP:云服务提供商会自动分配一个外部 IP。
示例:
apiVersion: v1 # 指定 Kubernetes API 版本
kind: Service # 资源类型为 Service
metadata: # 元数据部分name: admin # Service 的名称
spec: # Service 的具体配置ports: # 定义 Service 的端口配置- port: 80 # Service 的端口号targetPort: 80 # 后端 Pod 的目标端口号selector: # 用于选择后端 Pod 的标签选择器app: admin # 匹配标签为 app=admin 的 Podtype: LoadBalancer # Service 类型为 LoadBalancer
2.5 ExternalName
ExternalName 类型的 Service 通过 DNS CNAME 记录将请求转发到指定的外部域名。这种类型的 Service 适用于将外部服务引入 Kubernetes 集群。
示例:
apiVersion: v1 # 指定 Kubernetes API 版本
kind: Service # 资源类型为 Service
metadata: # 元数据部分name: admin # Service 的名称
spec: # Service 的具体配置type: ExternalName # Service 类型为 ExternalNameexternalName: www.admin.org # 指定外部域名
三、IPVS 模式
IPVS(IP Virtual Server)是一种高性能的负载均衡解决方案,适用于大规模集群环境。与默认的 iptables 模式相比,IPVS 模式可以显著降低 CPU 资源消耗。
3.1 IPVS 模式配置
-
安装 IPVS 工具: 在所有节点上安装
ipvsadm
工具:yum install ipvsadm -y # 安装 IPVS 工具
-
修改 kube-proxy 配置: 将 kube-proxy 的代理模式切换为 IPVS 模式:
kubectl -n kube-system edit cm kube-proxy # 编辑 kube-proxy 配置
修改配置文件,将
mode
设置为ipvs
。 -
重启 kube-proxy Pod: 重启 kube-proxy Pod 以应用新的配置:
kubectl -n kube-system delete pods -l k8s-app=kube-proxy # 删除旧的 kube-proxy Pod
-
验证 IPVS 配置: 使用
ipvsadm -Ln
命令查看 IPVS 规则:ipvsadm -Ln # 查看 IPVS 规则
四、Ingress-nginx
Ingress-Nginx 是一个基于 Nginx 的 Kubernetes Ingress 控制器,它将外部 HTTP/HTTPS 流量路由到集群内的服务。Ingress 是一种用于控制和管理 HTTP/HTTPS 流量的 Kubernetes 资源,而 Ingress 控制器则是实现这些规则的实际组件
4.1 Ingress 的功能
-
全局负载均衡:Ingress 提供的全局负载均衡能力,使得 Kubernetes 集群能够通过一个统一的入口管理外部流量,并根据规则将流量智能地分发到不同的后端服务。
-
支持 7 层功能:支持 HTTP/HTTPS 路由、重定向、认证等功能。
-
动态配置:Ingress Controller 是一个实际运行的组件,负责监听 Ingress 资源的变化,并根据这些资源定义的规则动态调整其内部配置。
4.2 部署 Ingress-nginx
-
下载部署文件: 下载 Ingress-nginx 的部署文件:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.2/deploy/static/provider/baremetal/deploy.yaml
-
修改镜像地址: 如果使用私有镜像仓库,需要修改部署文件中的镜像地址。
-
部署 Ingress-nginx: 应用部署文件:
kubectl apply -f deploy.yaml # 应用 Ingress-nginx 部署文件
-
验证部署: 检查 Ingress-nginx 的 Pod 和 Service 是否正常运行:
kubectl -n ingress-nginx get pods # 查看 Ingress-nginx 的 Pod 状态 kubectl -n ingress-nginx get svc # 查看 Ingress-nginx 的 Service 状态
4.3 Ingress 的高级用法
4.3.1 基于路径的访问
通过 Ingress 的路径规则,可以将不同路径的请求转发到不同的后端服务。
apiVersion: networking.k8s.io/v1 # 指定 Kubernetes API 版本
kind: Ingress # 资源类型为 Ingress
metadata: # 元数据部分name: ingress1 # Ingress 的名称
spec: # Ingress 的具体配置ingressClassName: nginx # 指定 Ingress 类型为 nginxrules: # 定义规则- host: www.admin.org # 指定主机名http: # 定义 HTTP 规则paths: # 定义路径规则- path: /v1 # 路径为 /v1pathType: Prefix # 路径类型为前缀匹配backend: # 后端服务配置service: # 指定后端服务name: myapp-v1 # 服务名称port: # 服务端口number: 80 # 端口号- path: /v2 # 路径为 /v2pathType: Prefix # 路径类型为前缀匹配backend: # 后端服务配置service: # 指定后端服务name: myapp-v2 # 服务名称port: # 服务端口number: 80 # 端口号
4.3.2 基于域名的访问
通过 Ingress 的主机名规则,可以将不同域名的请求转发到不同的后端服务。
apiVersion: networking.k8s.io/v1 # 指定 Kubernetes API 版本
kind: Ingress # 资源类型为 Ingress
metadata: # 元数据部分name: ingress2 # Ingress 的名称
spec: # Ingress 的具体配置ingressClassName: nginx # 指定 Ingress 类型为 nginxrules: # 定义规则- host: myappv1.admin.org # 指定主机名http: # 定义 HTTP 规则paths: # 定义路径规则- path: / # 路径为 /pathType: Prefix # 路径类型为前缀匹配backend: # 后端服务配置service: # 指定后端服务name: myapp-v1 # 服务名称port: # 服务端口number: 80 # 端口号- host: myappv2.admin.org # 指定主机名http: # 定义 HTTP 规则paths: # 定义路径规则- path: / # 路径为 /pathType: Prefix # 路径类型为前缀匹配backend: # 后端服务配置service: # 指定后端服务name: myapp-v2 # 服务名称port: # 服务端口number: 80 # 端口号
4.3.3 TLS 加密
通过 Ingress 的 TLS 功能,可以为服务启用 HTTPS 加密。
# 创建 TLS 证书
openssl req -newkey rsa:2048 -nodes -keyout tls.key -x509 -days 365 -subj "/CN=nginxsvc/O=nginxsvc" -out tls.crt
# 创建 Secret
kubectl create secret tls web-tls-secret --key tls.key --cert tls.crt
apiVersion: networking.k8s.io/v1 # 指定 Kubernetes API 版本
kind: Ingress # 资源类型为 Ingress
metadata: # 元数据部分name: ingress3 # Ingress 的名称
spec: # Ingress 的具体配置tls: # 定义 TLS 配置- hosts: # 定义支持的主机名- myapp-tls.admin.org # 主机名secretName: web-tls-secret # 引用的 TLS Secret 名称ingressClassName: nginx # 指定 Ingress 类型为 nginxrules: # 定义规则- host: myapp-tls.admin.org # 指定主机名http: # 定义 HTTP 规则paths: # 定义路径规则- path: / # 路径为 /pathType: Prefix # 路径类型为前缀匹配backend: # 后端服务配置service: # 指定后端服务name: myapp-v1 # 服务名称port: # 服务端口number: 80 # 端口号
4.3.4 基于用户认证
通过 Ingress 的认证功能,可以为服务添加用户认证。
# 创建认证文件
htpasswd -cm auth admin
apiVersion: networking.k8s.io/v1 # 指定 Kubernetes API 版本
kind: Ingress # 资源类型为 Ingress
metadata: # 元数据部分annotations: # 定义注解nginx.ingress.kubernetes.io/auth-type: basic # 认证类型为基本认证nginx.ingress.kubernetes.io/auth-secret: auth-web # 引用的认证 Secret 名称nginx.ingress.kubernetes.io/auth-realm: "Please input username and password" # 认证提示信息name: ingress4 # Ingress 的名称
spec: # Ingress 的具体配置tls: # 定义 TLS 配置- hosts: # 定义支持的主机名- myapp-tls.admin.org # 主机名secretName: web-tls-secret # 引用的 TLS Secret 名称ingressClassName: nginx # 指定 Ingress 类型为 nginxrules: # 定义规则- host: myapp-tls.admin.org # 指定主机名http: # 定义 HTTP 规则paths: # 定义路径规则- path: / # 路径为 /pathType: Prefix # 路径类型为前缀匹配backend: # 后端服务配置service: # 指定后端服务name: myapp-v1 # 服务名称port: # 服务端口number: 80 # 端口号
4.3.5 URL 重定向
通过 Ingress 的重定向功能,可以将请求重定向到指定的路径。
apiVersion: networking.k8s.io/v1 # 指定 Kubernetes API 版本
kind: Ingress # 资源类型为 Ingress
metadata: # 元数据部分annotations: # 定义注解nginx.ingress.kubernetes.io/rewrite-target: /$2 # 重定向目标路径nginx.ingress.kubernetes.io/use-regex: "true" # 启用正则表达式name: ingress5 # Ingress 的名称
spec: # Ingress 的具体配置ingressClassName: nginx # 指定 Ingress 类型为 nginxrules: # 定义规则- host: myapp-tls.admin.org # 指定主机名http: # 定义 HTTP 规则paths: # 定义路径规则- path: /lee(/|$)(.*) # 匹配路径 /lee/ 或 /leepathType: ImplementationSpecific # 路径类型为特定实现backend: # 后端服务配置service: # 指定后端服务name: myapp-v1 # 服务名称port: # 服务端口number: 80 # 端口号
五、Canary 金丝雀发布
5.1 什么是金丝雀发布
金丝雀发布是一种软件发布策略,通过将新版本的服务逐步暴露给部分用户,以降低新版本可能带来的风险。如果新版本运行正常,则逐步扩大范围,最终完成全面更新。
5.2 金丝雀发布方式
5.2.1 基于 Header 的灰度发布
通过 HTTP Header 来控制流量的分发,适用于需要逐步验证新版本的场景。
apiVersion: networking.k8s.io/v1 # 指定 Kubernetes API 版本
kind: Ingress # 资源类型为 Ingress
metadata: # 元数据部分annotations: # 定义注解nginx.ingress.kubernetes.io/canary: "true" # 启用金丝雀发布nginx.ingress.kubernetes.io/canary-by-header: "version" # 指定 Header 名称nginx.ingress.kubernetes.io/canary-by-header-value: "2" # 指定 Header 值name: myapp-v2-ingress # Ingress 的名称
spec: # Ingress 的具体配置ingressClassName: nginx # 指定 Ingress 类型为 nginxrules: # 定义规则- host: myapp.admin.org # 指定主机名http: # 定义 HTTP 规则paths: # 定义路径规则- path: / # 路径为 /pathType: Prefix # 路径类型为前缀匹配backend: # 后端服务配置service: # 指定后端服务name: myapp-v2 # 服务名称port: # 服务端口number: 80 # 端口号
5.2.2 基于权重的灰度发布
通过配置权重来控制流量的分发,适用于需要逐步调整流量比例的场景。
apiVersion: networking.k8s.io/v1 # 指定 Kubernetes API 版本
kind: Ingress # 资源类型为 Ingress
metadata: # 元数据部分annotations: # 定义注解nginx.ingress.kubernetes.io/canary: "true" # 启用金丝雀发布nginx.ingress.kubernetes.io/canary-weight: "10" # 新版本权重nginx.ingress.kubernetes.io/canary-weight-total: "100" # 总权重name: myapp-v2-ingress # Ingress 的名称
spec: # Ingress 的具体配置ingressClassName: nginx # 指定 Ingress 类型为 nginxrules: # 定义规则- host: myapp.admin.org # 指定主机名http: # 定义 HTTP 规则paths: # 定义路径规则- path: / # 路径为 /pathType: Prefix # 路径类型为前缀匹配backend: # 后端服务配置service: # 指定后端服务name: myapp-v2 # 服务名称port: # 服务端口number: 80 # 端口号