Kubernetes
什么是 Kubernetes
Kubernetes(简称 K8s)是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用程序。它由 Google 开发并捐赠给云原生计算基金会(CNCF)。
核心功能
- 服务发现与负载均衡:自动将流量分发到多个容器实例
- 存储编排:自动挂载存储系统(本地存储、云存储等)
- 自动部署和回滚:管理应用的发布版本,支持快速回滚
- 自动装箱:根据资源需求和约束自动调度容器
- 自我修复:自动重启失败容器、替换和重新调度异常节点上的容器
- 密钥和配置管理:管理敏感信息和应用配置
应用场景
- 微服务架构部署与管理
- 持续集成/持续部署(CI/CD)
- 混合云和多云环境管理
- 大数据处理
- 机器学习训练与推理
安装 Kubernetes
这里使用的是kubeasz来安装 Kubernetes。
在学习阶段可以使用all in one来安装 Kubernetes。
架构组件
Kubernetes 采用主从架构,主要分为控制平面(Control Plane)和工作节点(Worker Node)两部分。
控制平面组件
控制平面负责管理集群状态,做出全局决策。
kube-apiserver
集群的统一入口,所有请求都通过 API Server 进行处理。提供认证、授权、访问控制、API 注册和发现等机制。
etcd
高可用的键值数据库,用于存储集群所有状态数据。是 Kubernetes 的唯一数据源。
kube-scheduler
负责 Pod 的调度,根据资源需求、策略约束、亲和性规则等将 Pod 分配到合适的节点。
kube-controller-manager
运行控制器进程,包括:
- 节点控制器(Node Controller)
- 副本控制器(Replication Controller)
- 端点控制器(Endpoints Controller)
- 服务账户和令牌控制器(Service Account & Token Controllers)
cloud-controller-manager
将集群连接到云服务商的 API,实现与云平台的集成。
工作节点组件
工作节点负责运行容器组。
kubelet
节点上的主要代理,负责:
- 监听 API Server 的调度指令
- 挂载 Pod 所需的存储卷
- 下载 Pod 所需的 Secret
- 通过容器运行时接口(CRI)运行容器
- 定期执行容器健康检查
kube-proxy
网络代理,维护节点上的网络规则,实现 Service 的负载均衡和转发。
容器运行时(Container Runtime)
负责运行容器的软件,如 containerd、CRI-O、Docker Engine 等。
核心概念
Pod
Pod 是 Kubernetes 中最小的部署单元,包含一个或多个容器。同一个 Pod 内的容器共享网络命名空间和存储卷。
Namespace
用于在集群内实现资源隔离,不同命名空间的资源相互隔离。
Node
集群中的工作机器,可以是物理机或虚拟机。
基础资源对象
Pod
Pod 是 Kubernetes 中最小的部署单元。
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
resources:
# 一般生产环境最好请求和限制的资源设置为一样, 保证最大性能
requests:
cpu: "250m" # 请求 CPU 资源 0.25 核
memory: "64Mi" # 请求内存 64MB
limits:
cpu: "500m" # 限制最大 CPU 资源 0.5 核
memory: "128Mi" # 限制最大内存 128MB
Deployment
Deployment 提供声明式更新能力,管理 Pod 的副本数量和版本。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
Service
Service 定义一组 Pod 的访问策略,提供稳定的访问入口。
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Service 类型说明:
- ClusterIP:集群内部访问(默认)
- NodePort:通过节点端口暴露服务
- LoadBalancer:使用云厂商的负载均衡器
- ExternalName:映射到外部 DNS 名称
ConfigMap
用于存储非敏感配置数据。
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
database_host: "mysql-service"
database_port: "3306"
cache_ttl: "3600"
Secret
用于存储敏感信息,如密码、令牌、密钥等。
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2Rm
PersistentVolume 和 PersistentVolumeClaim
用于持久化存储管理。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-storage
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain
storageClassName: standard
hostPath:
path: /mnt/data
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-storage
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: standard
常用命令
集群管理
kubectl cluster-info
kubectl get nodes
kubectl describe node <node-name>
kubectl top nodes
资源查看
kubectl get pods
kubectl get pods -o wide
kubectl get pods --all-namespaces
kubectl get deployments
kubectl get services
kubectl get all
kubectl describe pod <pod-name>
kubectl logs <pod-name>
kubectl logs -f <pod-name>
kubectl exec -it <pod-name> -- /bin/bash
资源创建与更新
kubectl apply -f deployment.yaml
kubectl create -f deployment.yaml
kubectl edit deployment <deployment-name>
kubectl scale deployment <deployment-name> --replicas=5
kubectl set image deployment/<deployment-name> <container-name>=<new-image>
资源删除
kubectl delete -f deployment.yaml
kubectl delete pod <pod-name>
kubectl delete deployment <deployment-name>
kubectl delete service <service-name>
配置管理
kubectl create configmap <config-name> --from-literal=key=value
kubectl create configmap <config-name> --from-file=path/to/file
kubectl create secret generic <secret-name> --from-literal=key=value
kubectl get configmaps
kubectl get secrets
kubectl describe configmap <config-name>
调试与排查
kubectl describe pod <pod-name>
kubectl logs <pod-name> --previous
kubectl exec -it <pod-name> -- /bin/sh
kubectl port-forward <pod-name> 8080:80
kubectl cp <pod-name>:/path/to/file ./local-file
Helm 包管理器
Helm 是 Kubernetes 的包管理器,类似于 Linux 的 yum 或 apt,用于简化应用的部署和管理。
官方文档
核心概念
- Chart:应用包,包含一组 Kubernetes 资源定义文件
- Release:Chart 的一次安装实例
- Repository:Chart 的存储仓库
安装 Helm
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4
chmod 700 get_helm.sh
./get_helm.sh
常用命令
helm repo add <repo-name> <repo-url>
helm repo update
helm search repo <chart-name>
helm install <release-name> <chart> -n <namespace>
helm upgrade <release-name> <chart> -n <namespace>
helm rollback <release-name> <revision> -n <namespace>
helm uninstall <release-name> -n <namespace>
helm list -n <namespace>
helm status <release-name> -n <namespace>
Traefik 网关
Traefik 是一个现代化的 HTTP 反向代理和负载均衡器,专为微服务架构设计。
官方文档
安装 Traefik
helm repo add traefik https://traefik.github.io/charts
helm repo update
helm install traefik traefik/traefik -n traefik --create-namespace --values values.yaml
配置示例
values.yaml
deployment:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
ports:
web:
port: 80
hostPort: 80
websecure:
port: 443
hostPort: 443
port-40050:
port: 40050
hostPort: 40050
port-40033:
port: 40033
hostPort: 40033
api:
dashboard: true
insecure: false
ingressClass:
enabled: false
providers:
kubernetesIngress:
enabled: false
kubernetesGateway:
enabled: true
gateway:
listeners:
web:
port: 80
protocol: HTTP
namespacePolicy:
from: All
websecure:
port: 443
protocol: HTTPS
namespacePolicy:
from: All
mode: Terminate
certificateRefs:
- kind: Secret
name: local-selfsigned-tls
group: ""
port-40050:
port: 40050
protocol: HTTP
namespacePolicy:
from: All
port-40033:
port: 40033
protocol: HTTPS
namespacePolicy:
from: All
mode: Terminate
certificateRefs:
- kind: Secret
name: local-selfsigned-tls
group: ""
logs:
general:
level: INFO
access:
enabled: true
metrics:
prometheus:
enabled: true
测试部署
部署一个测试服务验证 Traefik 路由功能:
whoami-test.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami-test
namespace: traefik
spec:
replicas: 1
selector:
matchLabels:
app: whoami-test
template:
metadata:
labels:
app: whoami-test
spec:
containers:
- name: whoami
image: traefik/whoami
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: whoami-test-svc
namespace: traefik
spec:
selector:
app: whoami-test
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: port-40050
port: 40050
targetPort: 80
- name: port-40033
port: 40033
targetPort: 80
type: ClusterIP
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: whoami-test
namespace: traefik
spec:
parentRefs:
- name: traefik-gateway
hostnames:
- "whoami.k8s.tteam.icu"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: whoami-test-svc
port: 80
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: whoami-test-svc
port: 40050
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: whoami-test-svc
port: 40033
最佳实践
资源限制
为所有容器设置资源请求和限制,避免资源争抢:
resources:
# 一般生产环境最好请求和限制的资源设置为一样, 保证最大性能
requests:
cpu: "250m" # 请求 CPU 资源 0.25 核
memory: "64Mi" # 请求内存 64MB
limits:
cpu: "500m" # 限制最大 CPU 资源 0.5 核
memory: "128Mi" # 限制最大内存 128MB
健康检查
配置存活探针和就绪探针:
livenessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
安全配置
- 使用非 root 用户运行容器
- 设置只读文件系统
- 限制能力(Capabilities)
- 使用 Pod Security Standards
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
配置管理
- 使用 ConfigMap 管理应用配置
- 使用 Secret 管理敏感信息
- 使用环境变量注入配置
版本控制
- 使用 GitOps 管理集群配置
- 使用声明式配置而非命令式
- 保持配置文件的版本化
故障排查
Pod 状态异常
kubectl describe pod <pod-name>
kubectl logs <pod-name>
kubectl get events --sort-by='.lastTimestamp'
服务无法访问
kubectl get endpoints <service-name>
kubectl describe service <service-name>
kubectl exec -it <pod-name> -- nslookup <service-name>
持久化存储问题
kubectl get pv
kubectl get pvc
kubectl describe pvc <pvc-name>
节点问题
kubectl describe node <node-name>
kubectl get events --field-selector involvedObject.kind=Node