Kubernetes网络与基础设施管理全解析
一、高级Kubernetes网络
1. Ingress控制器
目前有两个官方的Ingress控制器。一个是仅适用于GCE的L7 Ingress控制器,另一个是更通用的NGINX Ingress控制器,它允许通过ConfigMap配置NGINX。NGINX Ingress控制器非常复杂,具有许多无法直接通过Ingress资源实现的功能。它使用端点API将流量直接转发到Pod,支持Minikube、GCE、AWS、Azure和裸机集群。详细信息可查看:https://github.com/kubernetes/ingress-nginx 。
以下是一个Ingress配置示例:
- host: foo.bar.com
http:
paths:
- path: /foo
backend:
serviceName: s1
servicePort: 80
- path: /bar
backend:
serviceName: s2
servicePort: 80
2. HAProxy负载均衡
可以使用云提供商的外部负载均衡器(服务类型为LoadBalancer),也可以在集群内部使用内部服务负载均衡器(ClusterIP)。若需要自定义外部负载均衡器,可创建自定义外部负载均衡器提供商并使用LoadBalancer,或者使用第三种服务类型NodePort。
HAProxy是一个成熟且经过实战检验的负载均衡解决方案,被认为是在本地集群中实现外部负载均衡的最佳选择,可通过以下几种方式实现:
- 利用NodePort并谨慎管理端口分配。
- 实现自定义负载均衡器提供商接口。
- 在集群内运行HAProxy,作为集群边缘前端服务器的唯一目标(无论是否进行负载均衡)。
社区项目service - loadbalancer基于HAProxy实现了负载均衡解决方案,可在https://github.com/kubernetes/contrib/tree/master/service - loadbalancer 找到。
- 利用NodePort :每个服务会从预定义的范围(通常是30000及以上的高范围,以避免与使用低知名端口的其他应用冲突)分配一个专用端口。此时HAProxy在集群外运行,需为其配置每个服务的正确端口,然后将流量转发到任何节点,Kubernetes通过内部服务将流量路由到合适的Pod(双重负载均衡),这种方式效率不高,因为增加了一跳。可通过查询端点API并动态管理每个服务的后端Pod列表,直接将流量转发到Pod来解决。
- 使用HAProxy的自定义负载均衡器提供商 :这种方法稍复杂,但好处是能更好地与Kubernetes集成,使本地与云之间的过渡更轻松。
- 在Kubernetes集群内运行HAProxy :使用集群内的内部HAProxy负载均衡器,可能有多个节点运行HAProxy,它们共享相同的配置,以映射传入请求并在后端服务器之间进行负载均衡。
3. Keepalived VIP
Keepalived VirtualIP(VIP)本身不一定是负载均衡解决方案,它可以作为NGINX Ingress控制器或基于HAProxy的服务LoadBalancer的补充。主要原因是Kubernetes中的Pod会移动,包括负载均衡器,这给需要稳定端点的外部客户端带来问题。由于性能问题,DNS通常不够好。Keepalived提供高性能虚拟IP地址,可作为NGINX Ingress控制器或HAProxy负载均衡器的地址。它利用核心Linux网络设施(如IPVS),通过虚拟冗余路由器协议(VRRP)实现高可用性,一切在第4层(TCP/UDP)运行,配置需要一定的精力和细节关注。Kubernetes contrib项目可帮助入门:https://github.com/kubernetes/contrib/tree/master/keepalived - vip 。
4. Træfic
Træfic是现代HTTP反向代理和负载均衡器,专为支持微服务而设计,可与包括Kubernetes在内的许多后端协作,自动动态管理配置,与传统负载均衡器相比是一个变革。它具有以下令人印象深刻的特性:
- 快速
- 单Go可执行文件
- 微小的官方Docker镜像
- REST API
- 配置热重载,无需重启进程
- 断路器、重试
- 轮询、重新平衡负载均衡器
- 指标(REST、Prometheus、Datadog、Statsd、InfluxDB)
- 简洁的AngularJS Web UI
- 支持Websocket、HTTP/2、GRPC
- 访问日志(JSON、CLF)
- Let’s Encrypt支持(自动HTTPS及续订)
- 集群模式下的高可用性
5. 编写自己的CNI插件
CNI插件是一个可执行文件,负责将新容器连接到网络,为CNI容器分配唯一IP地址并处理路由。容器是一个网络命名空间(在Kubernetes中,Pod是CNI容器),网络定义以JSON文件管理,但通过标准输入流式传输到插件(插件不读取文件),辅助信息可通过环境变量提供。
- 初探回环插件 :回环插件仅添加回环接口,非常简单,不需要任何网络配置信息。大多数CNI插件用Golang实现,回环CNI插件也不例外,完整源代码可在https://github.com/containernetworking/plugins/blob/master/plugins/main/loopback 找到。以下是其部分代码:
package main
import (
"github.com/containernetworking/cni/pkg/ns"
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types/current"
"github.com/containernetworking/cni/pkg/version"
"github.com/vishvananda/netlink"
)
func cmdAdd(args *skel.CmdArgs) error {
args.IfName = "lo"
err := ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {
link, err := netlink.LinkByName(args.IfName)
if err != nil {
return err // not tested
}
err = netlink.LinkSetUp(link)
if err != nil {
return err // not tested
}
return nil
})
if err != nil {
return err // not tested
}
result := current.Result{}
return result.Print()
}
func cmdDel(args *skel.CmdArgs) error {
args.IfName = "lo"
err := ns.WithNetNSPath(args.Netns, func(ns.NetNS) error {
link, err := netlink.LinkByName(args.IfName)
if err != nil {
return err // not tested
}
err = netlink.LinkSetDown(link)
if err != nil {
return err // not tested
}
return nil
})
if err != nil {
return err // not tested
}
result := current.Result{}
return result.Print()
}
func main() {
skel.PluginMain(cmdAdd, cmdDel, version.All)
}
-
基于CNI插件骨架构建
:
skel包的PluginMain负责调用PluginMainWithError,捕获错误,将其打印到标准输出并退出。PluginErrorWithMain实例化一个调度器,设置所有I/O流和环境,并调用其pluginMain方法。pluginMain从环境中获取命令参数,检测调用的命令,并调用适当的插件函数(cmdAdd或cmdDel),还可以返回版本信息。 - 回顾桥接插件 :桥接插件更复杂,其完整源代码可在https://github.com/containernetworking/plugins/blob/master/plugins/main/bridge 找到。它定义了一个网络配置结构体:
type NetConf struct {
types.NetConf
BrName string `json:"bridge"`
IsGW bool `json:"isGateway"`
IsDefaultGW bool `json:"isDefaultGateway"`
ForceAddress bool `json:"forceAddress"`
IPMasq bool `json:"ipMasq"`
MTU int `json:"mtu"`
HairpinMode bool `json:"hairpinMode"`
PromiscMode bool `json:"promiscMode"`
}
配置通过
loadNetConf
函数从JSON加载,在
cmdAdd
和
cmdDel
函数开始时调用。
cmdAdd
函数的核心是使用网络配置信息设置veth,与IPAM插件交互以添加适当的IP地址并返回结果。
二、Kubernetes基础设施管理
1. 集群规划
构建Kubernetes集群有很多选择,规划时需要考虑以下关键领域:
-
选择合适的平台
:
-
本地解决方案
:
- Minikube:单节点Kubernetes集群。
- Ubuntu on LXD:使用LXD部署包含九个实例的Kubernetes集群。
- IBM’s Cloud Private - CE:使用VirtualBox在n + 1个实例上部署Kubernetes。
- kubeadm - dind(Docker - in - Docker):支持多节点Kubernetes集群。
-
托管解决方案
:
- Google Kubernetes Engine
- Amazon Elastic Container Services
- Azure Kubernetes Service
- Stackpoint
- Openshift online
- IBM Cloud Kubernetes Services
- Giant Swarm
更多交钥匙解决方案可查看https://kubernetes.io/docs/setup/pick - right - solution/#turnkey - cloud - solutions 。
2. 集群安全
确保对集群配置进行以下方面的配置更改:
-
日志记录
:确保启用Kubernetes日志,可在https://kubernetes.io/docs/tasks/debug - application - cluster/audit/ 了解更多审计日志信息。
-
身份验证
:确保启用身份验证,让用户、操作员和服务以唯一标识符进行身份识别,可在https://kubernetes.io/docs/reference/access - authn - authz/authentication/ 了解更多信息。
-
授权
:确保使用授权实现职责分离、基于角色的访问控制和细粒度权限,可在https://kubernetes.io/docs/reference/access - authn - authz/authorization/ 了解更多基于HTTP的控制信息。
-
API访问控制
:确保将API锁定到特定权限和组,可在https://kubernetes.io/docs/reference/access - authn - authz/controlling - access/ 了解更多API访问信息。
-
准入控制器
:在适当的时候启用准入控制器,在请求通过身份验证和授权控制后进一步重新验证请求,可在https://kubernetes.io/docs/reference/access - authn - authz/controlling - access 了解更多信息。
-
调整Linux系统参数
:通过sysctl接口调整Linux系统参数,可修改节点级和命名空间sysctl功能的内核参数,有安全和不安全的系统参数,可调整的子系统包括:
- abi:执行域和个性
- fs:特定文件系统、文件句柄、inode、dentry和配额调整
- kernel:全局内核信息/调整
- net:网络
- sunrpc:SUN远程过程调用(RPC)
- vm:内存管理调整、缓冲区和缓存管理
- user:每个用户每个用户命名空间限制
可在https://kubernetes.io/docs/tasks/administer - cluster/sysctl - cluster/ 了解更多sysctl调用信息。可通过以下命令启用不安全的sysctl值:
kubelet --allowed - unsafe - sysctls ‘net.ipv4.route.min_pmtu'
以下是一个调整sysctl的Pod示例:
apiVersion: v1
kind: Pod
metadata:
name: sysctl - example
spec:
securityContext:
sysctls:
- name: kernel.shm_rmid_forced
value: "0"
- name: net.core.somaxconn
value: "10000"
- name: kernel.msgmax
value: "65536"
- name: ipv4.ip_local_port_range
value: ‘1024 65535'
还可以调整ARP缓存等变量,例如:
net.ipv4.neigh.default.gc_thresh1 = 90000
net.ipv4.neigh.default.gc_thresh2 = 100000
net.ipv4.neigh.default.gc_thresh3 = 120000
3. 集群升级
运行集群需要根据需要进行更新,集群升级的难度取决于所选平台。一般来说,托管平台即服务(PaaS)选项更简单,而自行搭建的选项则需要自己管理集群升级。
-
升级PaaS集群
:
-
Azure
:管理Azure Kubernetes Service(AKS)集群的控制平面和节点升级相对简单。可使用以下命令检查可用的升级:
az aks get - upgrades --name “myAKSCluster” --resource - group myResourceGroup - output table
升级时必须通过小版本进行,AKS会处理添加新节点、隔离和排空节点的过程,以防止对正在运行的应用程序造成中断。可使用以下命令进行升级:
az aks upgrade --name myAKSCluster --resource - group myResourceGroup --kubernetes - version 1.9.6
还可使用以下命令显示当前版本:
az aks show --name myAKSCluster --resource - group myResourceGroup --output table
- **GCE**:GCE有两种更新集群的机制。对于管理节点升级,GCP使用相同的持久磁盘(PD)删除并重新创建主节点以保留升级过程中的状态;对于工作节点,使用GCP的管理实例组进行滚动升级,销毁并替换每个节点以避免对工作负载造成中断。可使用以下命令将集群主节点升级到特定版本:
cluster/gce/upgrade.sh - M v1.0.2
也可使用相同命令更新整个集群。
-
Google Kubernetes Engine
:升级Google Kubernetes Engine集群有简单的用户发起选项。需要设置项目ID:
gcloud config set project [PROJECT_ID]
并确保拥有最新的gcloud组件:
gcloud components update
更新GCP上的Kubernetes集群时,可降级节点,但不能降级主节点。GKE会处理节点和Pod的排空,而不会中断应用程序,替换节点将以与前身相同的节点和配置重新创建,还会更新以下集群组件的软件:
- kubelet
- kube - proxy
- Docker守护程序
- 操作系统
可使用以下命令查看服务器的升级选项:
gcloud container get - server - config
要注意,升级过程中存储在hostPath和emptyDir目录中的数据将被删除,只有PD会被保留。可通过GKE开启节点自动更新,或手动执行更新。可在https://cloud.google.com/kubernetes - engine/docs/concepts/node - auto - upgrades 了解如何开启自动节点升级,也可使用以下命令创建默认开启自动升级的集群:
gcloud container clusters create [CLUSTER_NAME] --zone [COMPUTE_ZONE] --enable - autoupgrade
综上所述,Kubernetes的网络和基础设施管理涉及众多方面,无论是网络的负载均衡、自定义插件编写,还是基础设施的规划、安全和升级,都需要根据实际需求和场景进行选择和配置,以构建稳定、高效、安全的Kubernetes集群。
Kubernetes网络与基础设施管理全解析
三、集群扩展
集群扩展是确保Kubernetes集群能够应对不断增长的工作负载需求的重要操作。以下是一些常见的集群扩展方法:
1. 节点扩展
- 手动添加节点 :可以通过在现有集群中添加新的计算节点来扩展集群容量。在不同的云平台上,操作步骤有所不同。例如,在AWS上,可以启动新的EC2实例,并将其加入到Kubernetes集群中。首先,需要确保新实例的操作系统和网络配置与现有集群兼容。然后,使用kubeadm等工具将新节点加入集群。
# 在新节点上执行以下命令加入集群
kubeadm join <master - ip>:<master - port> --token <token> --discovery - token - ca - cert - hash <hash>
- 自动扩展 :一些云平台提供了自动节点扩展的功能。例如,在Google Kubernetes Engine(GKE)中,可以使用节点自动扩展器(Node Auto - Provisioning)。通过设置节点池的最小和最大节点数,当集群中的工作负载增加时,GKE会自动添加新的节点;当工作负载减少时,会自动删除多余的节点。
# 创建支持自动扩展的节点池
gcloud container node - pools create [NODE_POOL_NAME] --cluster [CLUSTER_NAME] --zone [COMPUTE_ZONE] --enable - autoscaling --min - nodes [MIN_NODES] --max - nodes [MAX_NODES]
2. 资源扩展
-
Pod资源请求和限制调整
:可以通过调整Pod的资源请求和限制来扩展集群内的资源使用。在Pod的YAML配置文件中,可以修改
resources字段。
apiVersion: v1
kind: Pod
metadata:
name: resource - example
spec:
containers:
- name: my - container
image: my - image
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
- Horizontal Pod Autoscaler(HPA) :HPA可以根据Pod的CPU使用率、内存使用率等指标自动调整Pod的副本数。首先,需要确保Metrics Server在集群中运行,以提供资源指标。
# 部署Metrics Server
kubectl apply - f https://github.com/kubernetes-sigs/metrics - server/releases/latest/download/components.yaml
然后,创建HPA对象。
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: my - hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my - deployment
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
四、集群维护
集群维护是保证Kubernetes集群稳定运行的关键,以下是一些重要的集群维护任务:
1. 节点维护
-
节点隔离和排空
:在对节点进行维护(如升级操作系统、硬件维护等)之前,需要将节点隔离并排空其上的Pod。可以使用
kubectl drain命令。
# 隔离并排空节点
kubectl drain <node - name> --ignore - daemonsets --delete - local - data
该命令会将节点标记为不可调度,然后将其上的Pod迁移到其他节点。
-
节点恢复
:维护完成后,需要将节点恢复为可调度状态。
# 恢复节点可调度状态
kubectl uncordon <node - name>
2. 备份和恢复
-
Etcd备份
:Etcd是Kubernetes集群的核心数据存储,需要定期备份。可以使用
etcdctl命令进行备份。
# 备份Etcd数据
ETCDCTL_API=3 etcdctl --endpoints=https://<etcd - endpoint>:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/peer.crt --key=/etc/kubernetes/pki/etcd/peer.key snapshot save /var/lib/etcd/snapshot.db
- 恢复Etcd数据 :在需要时,可以使用备份文件恢复Etcd数据。
# 恢复Etcd数据
ETCDCTL_API=3 etcdctl --data - dir=/var/lib/etcd - new snapshot restore /var/lib/etcd/snapshot.db
五、SIG Cluster Lifecycle组
SIG(Special Interest Group)Cluster Lifecycle组是Kubernetes社区中专注于集群生命周期管理的组织。该组致力于解决与集群部署、升级、扩展和维护相关的问题。
1. 主要工作内容
- 标准制定 :制定集群生命周期管理的标准和最佳实践,确保不同的Kubernetes发行版和部署方式具有一致性和互操作性。
- 工具开发 :开发和维护用于集群管理的工具,如kubeadm、kube - bench等。kubeadm是一个用于快速部署Kubernetes集群的工具,简化了集群的初始化和节点加入过程。
# 使用kubeadm初始化集群
kubeadm init --pod - network - cidr=10.244.0.0/16
- 问题解决 :处理社区中关于集群生命周期管理的问题和反馈,不断改进和优化相关的流程和工具。
2. 参与方式
开发者和用户可以通过参与SIG Cluster Lifecycle组的会议、提交代码贡献、参与讨论等方式加入该组。可以在Kubernetes官方网站上找到该组的相关信息和参与指南。
六、技术要求
在学习和实践Kubernetes的网络和基础设施管理时,需要满足以下技术要求:
1. 云平台账户
可以使用Google Cloud Platform(GCP)账户,需要确保账户已启用并已登录。也可以使用本地的Minikube实例,Minikube是一个轻量级的Kubernetes实现,适合本地开发和测试。
# 安装Minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube - linux - amd64
sudo install minikube - linux - amd64 /usr/local/bin/minikube
# 启动Minikube
minikube start
还可以通过网页使用Play with Kubernetes(https://labs.play - with - k8s.com/ )。
2. 工具安装
需要安装kubectl,它是Kubernetes的命令行工具,用于与Kubernetes集群进行交互。
# 在Linux上安装kubectl
curl -LO "https://dl.k8s.io/release/$(curl - L - s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install - o root - g root - m 0755 kubectl /usr/local/bin/kubectl
综上所述,Kubernetes的网络和基础设施管理是一个复杂而重要的领域。从网络的负载均衡、自定义插件编写,到基础设施的规划、安全、升级、扩展和维护,每个方面都需要深入理解和谨慎操作。通过合理运用各种技术和工具,结合实际的业务需求和场景,能够构建出稳定、高效、安全的Kubernetes集群,为应用程序的运行提供坚实的基础。同时,积极参与Kubernetes社区的活动,如SIG Cluster Lifecycle组的工作,也有助于不断提升技术水平和推动Kubernetes生态的发展。
超级会员免费看
1151

被折叠的 条评论
为什么被折叠?



