Kubernetes 教程:容器编排平台详解
1. 什么是 Kubernetes?
Kubernetes(简称 K8s)是一个开源的容器编排平台,用于自动化容器的部署、扩展和管理。它由 Google 设计并捐赠给 Cloud Native Computing Foundation(CNCF)管理,是目前最流行的容器编排解决方案。
1.1 核心概念
- Pod:Kubernetes 中最小的部署单元,包含一个或多个容器。
- Deployment:管理 Pod 的副本,确保指定数量的 Pod 运行。
- Service:为 Pod 提供稳定的网络访问方式。
- Namespace:用于在集群中创建隔离的资源组。
- Node:集群中的工作机器,可以是物理机或虚拟机。
- Cluster:由一组 Node 组成的 Kubernetes 集群。
- Control Plane:集群的控制中心,包含 API Server、Scheduler、Controller Manager 等组件。
- etcd:分布式键值存储,用于存储集群配置和状态。
1.2 核心特性
- 自动扩缩容:根据负载自动调整 Pod 数量。
- 服务发现和负载均衡:为 Pod 提供稳定的网络访问和负载均衡。
- 存储编排:自动挂载存储卷,支持多种存储系统。
- 自动修复:当 Pod 失败时自动重启或替换。
- 滚动更新:无缝更新应用,零 downtime。
- Secret 和配置管理:安全管理敏感信息和配置。
- 批量执行:支持一次性任务和定时任务。
1.3 适用场景
- 微服务架构:管理大量微服务的部署和扩展。
- 高可用性应用:确保应用持续运行,即使在节点故障时。
- 弹性伸缩:根据流量自动调整资源。
- 多环境部署:在不同环境中一致部署应用。
- 混合云和多云:在不同云提供商和本地环境中运行应用。
2. 安装和配置
2.1 本地开发环境
2.1.1 Minikube
Minikube 是一个用于在本地运行单节点 Kubernetes 集群的工具,适合开发和测试:
# 安装 Minikube(Windows)
choco install minikube
# 安装 Minikube(macOS)
brew install minikube
# 安装 Minikube(Linux)
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
# 启动 Minikube
minikube start
# 验证集群状态
kubectl cluster-info2.1.2 Kind
Kind(Kubernetes IN Docker)是一个使用 Docker 容器运行本地 Kubernetes 集群的工具:
# 安装 Kind
brew install kind # macOS
choco install kind # Windows
# 创建集群
kind create cluster
# 验证集群状态
kubectl cluster-info2.2 生产环境
2.2.1 Kubeadm
Kubeadm 是官方推荐的用于创建生产级 Kubernetes 集群的工具:
# 在所有节点上安装 Docker 或 Containerd
# 安装 kubeadm、kubelet 和 kubectl
apt-get update && apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
# 在主节点上初始化集群
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
# 配置 kubectl
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
# 安装网络插件
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
# 加入工作节点
# 在主节点上运行 kubeadm token create --print-join-command 获取加入命令
# 在工作节点上运行获取的命令2.2.2 托管 Kubernetes 服务
各大云提供商都提供托管的 Kubernetes 服务:
- Amazon EKS:Amazon Elastic Kubernetes Service
- Azure AKS:Azure Kubernetes Service
- Google GKE:Google Kubernetes Engine
- 阿里云 ACK:Alibaba Cloud Container Service for Kubernetes
- 腾讯云 TKE:Tencent Kubernetes Engine
2.3 配置 kubectl
kubectl 是 Kubernetes 的命令行工具,用于与集群交互:
# 安装 kubectl(Windows)
choco install kubernetes-cli
# 安装 kubectl(macOS)
brew install kubectl
# 安装 kubectl(Linux)
curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl
# 验证安装
kubectl version --client3. 基本使用
3.1 部署应用
# 使用 kubectl create 部署应用
kubectl create deployment nginx --image=nginx
# 暴露服务
kubectl expose deployment nginx --port=80 --type=NodePort
# 查看服务
kubectl get services
# 查看 Pod
kubectl get pods
# 查看部署
kubectl get deployments3.2 使用 YAML 文件部署
创建一个 nginx-deployment.yaml 文件:
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.14.2
ports:
- containerPort: 80apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
type: NodePort# 应用部署文件
kubectl apply -f nginx-deployment.yaml
# 应用服务文件
kubectl apply -f nginx-service.yaml
# 查看所有资源
kubectl get all3.3 扩缩容应用
# 手动扩缩容
kubectl scale deployment nginx-deployment --replicas=5
# 查看状态
kubectl get deployments
# 自动扩缩容
kubectl autoscale deployment nginx-deployment --min=2 --max=10 --cpu-percent=80
# 查看 HPA
kubectl get hpa3.4 滚动更新
# 滚动更新镜像
kubectl set image deployment nginx-deployment nginx=nginx:1.16.1
# 查看滚动更新状态
kubectl rollout status deployment nginx-deployment
# 回滚更新
kubectl rollout undo deployment nginx-deployment
# 查看历史版本
kubectl rollout history deployment nginx-deployment3.5 配置管理
3.5.1 ConfigMap
# 创建 ConfigMap
kubectl create configmap app-config --from-literal=DB_HOST=localhost --from-literal=DB_PORT=5432
# 查看 ConfigMap
kubectl get configmap
# 查看 ConfigMap 详情
kubectl describe configmap app-config3.5.2 Secret
# 创建 Secret
kubectl create secret generic app-secret --from-literal=DB_USER=admin --from-literal=DB_PASSWORD=secret
# 查看 Secret
kubectl get secret
# 查看 Secret 详情
kubectl describe secret app-secret4. 高级功能
4.1 存储管理
4.1.1 持久卷(Persistent Volume)
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"4.1.2 持久卷声明(Persistent Volume Claim)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: my-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi4.1.3 在 Pod 中使用持久卷
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-container
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: my-volume
volumes:
- name: my-volume
persistentVolumeClaim:
claimName: my-pvc4.2 网络策略
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
spec:
podSelector:
matchLabels:
app: backend
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 80804.3 资源配额
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: default
spec:
hard:
pods: "10"
requests.cpu: "4"
requests.memory: 8Gi
limits.cpu: "8"
limits.memory: 16Gi4.4 命名空间
# 创建命名空间
kubectl create namespace development
# 在命名空间中部署应用
kubectl apply -f nginx-deployment.yaml -n development
# 查看命名空间中的资源
kubectl get pods -n development
# 切换默认命名空间
kubectl config set-context --current --namespace=development5. 实用案例
5.1 部署一个简单的 Node.js 应用
场景:在 Kubernetes 集群中部署一个简单的 Node.js Express 应用。
步骤:
- 创建应用代码:
// app.js
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello Kubernetes!');
});
app.listen(port, () => {
console.log(`App listening at http://localhost:${port}`);
});// package.json
{
"name": "k8s-node-app",
"version": "1.0.0",
"description": "Node.js app on Kubernetes",
"main": "app.js",
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "^4.17.1"
}
}- 创建 Dockerfile:
FROM node:14-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]- 构建和推送镜像:
# 构建镜像
docker build -t your-dockerhub-username/node-app:v1 .
# 推送镜像
docker push your-dockerhub-username/node-app:v1- 创建 Kubernetes 部署文件:
# node-app-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app
image: your-dockerhub-username/node-app:v1
ports:
- containerPort: 3000
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"# node-app-service.yaml
apiVersion: v1
kind: Service
metadata:
name: node-app-service
spec:
selector:
app: node-app
ports:
- port: 80
targetPort: 3000
type: LoadBalancer- 部署应用:
kubectl apply -f node-app-deployment.yaml
kubectl apply -f node-app-service.yaml- 查看部署状态:
kubectl get all- 测试应用:
对于 Minikube:
minikube service node-app-service对于云提供商的托管 Kubernetes 服务,获取负载均衡器的外部 IP:
kubectl get services然后在浏览器中访问该 IP,应该看到 "Hello Kubernetes!"。
5.2 使用 Helm 部署应用
场景:使用 Helm 包管理器部署一个复杂的应用(如 WordPress)。
步骤:
- 安装 Helm:
# 安装 Helm(Windows)
choco install kubernetes-helm
# 安装 Helm(macOS)
brew install helm
# 安装 Helm(Linux)
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh- 添加 Helm 仓库:
helm repo add bitnami https://charts.bitnami.com/bitnami- 更新 Helm 仓库:
helm repo update- 部署 WordPress:
helm install my-wordpress bitnami/wordpress- 查看部署状态:
helm status my-wordpress
kubectl get all- 获取 WordPress 访问信息:
echo Username: user
echo Password: $(kubectl get secret my-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode)
echo External IP: $(kubectl get service my-wordpress --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")- 测试应用:
在浏览器中访问获取的外部 IP,使用获取的用户名和密码登录 WordPress。
- 删除部署:
helm uninstall my-wordpress6. 代码示例
6.1 基本部署示例
node-app-deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app-deployment
spec:
replicas: 2
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app
image: your-dockerhub-username/node-app:v1
ports:
- containerPort: 3000
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"node-app-service.yaml:
apiVersion: v1
kind: Service
metadata:
name: node-app-service
spec:
selector:
app: node-app
ports:
- port: 80
targetPort: 3000
type: LoadBalancer部署命令:
kubectl apply -f node-app-deployment.yaml
kubectl apply -f node-app-service.yaml
kubectl get all6.2 使用 ConfigMap 和 Secret
app-config.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DB_HOST: "db"
DB_PORT: "5432"
DB_NAME: "myapp"app-secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: app-secret
type: Opaque
data:
DB_USER: YWRtaW4=
DB_PASSWORD: c2VjcmV0node-app-with-config.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: node-app-with-config
spec:
replicas: 2
selector:
matchLabels:
app: node-app
template:
metadata:
labels:
app: node-app
spec:
containers:
- name: node-app
image: your-dockerhub-username/node-app:v1
ports:
- containerPort: 3000
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secret
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"部署命令:
kubectl apply -f app-config.yaml
kubectl apply -f app-secret.yaml
kubectl apply -f node-app-with-config.yaml
kubectl get configmap,secret7. 常见问题和解决方案
7.1 Pod 无法启动
问题:Pod 状态为 CrashLoopBackOff 或 ContainerCreating。
解决方案:
- 查看 Pod 日志:
kubectl logs [pod-name] - 查看 Pod 详情:
kubectl describe pod [pod-name] - 检查镜像是否存在
- 检查资源是否足够
- 检查网络配置
7.2 服务无法访问
问题:无法通过 Service 访问应用。
解决方案:
- 检查 Service 状态:
kubectl get service [service-name] - 检查 Service 详情:
kubectl describe service [service-name] - 检查 Pod 是否运行:
kubectl get pods - 检查 Pod 标签是否与 Service 选择器匹配
- 检查网络策略是否阻止访问
7.3 集群节点不可用
问题:节点状态为 NotReady。
解决方案:
- 查看节点状态:
kubectl get nodes - 查看节点详情:
kubectl describe node [node-name] - 检查节点上的 kubelet 服务是否运行
- 检查节点网络连接
- 检查节点资源是否足够
7.4 资源不足
问题:Pod 无法调度,提示资源不足。
解决方案:
- 检查节点资源:
kubectl describe node - 调整 Pod 的资源请求和限制
- 添加更多节点到集群
- 清理不需要的 Pod 和服务
7.5 滚动更新失败
问题:滚动更新卡住或失败。
解决方案:
- 查看滚动更新状态:
kubectl rollout status deployment [deployment-name] - 查看 Pod 日志:
kubectl logs [pod-name] - 回滚更新:
kubectl rollout undo deployment [deployment-name] - 检查应用的健康检查配置
8. 总结
Kubernetes 是一个功能强大的容器编排平台,它提供了完整的容器管理解决方案,包括部署、扩展、服务发现、负载均衡、存储编排等功能。通过 Kubernetes,开发者可以更加专注于应用的开发,而将部署和管理的复杂性交给平台处理。
8.1 优点
- 自动化管理:自动处理容器的部署、扩展和故障恢复
- 高可用性:确保应用持续运行,即使在节点故障时
- 弹性伸缩:根据负载自动调整资源
- 服务发现和负载均衡:为应用提供稳定的网络访问
- 存储编排:支持多种存储系统,提供灵活的存储解决方案
- 可扩展性:通过自定义资源和控制器扩展 Kubernetes 功能
- 多云支持:在不同云提供商和本地环境中运行一致
8.2 局限性
- 学习曲线陡峭:对于初学者来说,Kubernetes 有一定的学习曲线
- 复杂性:配置和管理 Kubernetes 集群需要一定的专业知识
- 资源开销:Kubernetes 本身需要一定的资源来运行
- 网络复杂性:网络配置可能变得复杂,特别是在多集群环境中
- 存储管理:存储配置和管理需要额外的考虑
8.3 适用场景
- 微服务架构:管理大量微服务的部署和扩展
- 高流量应用:需要自动扩缩容和高可用性的应用
- 企业级应用:需要严格的资源管理和安全控制的应用
- 多环境部署:在开发、测试和生产环境中一致部署应用
- 混合云和多云:在不同云提供商和本地环境中运行应用
通过本教程,你应该已经掌握了 Kubernetes 的基本概念、安装配置、基本使用和常见场景的应用。在实际开发和部署中,Kubernetes 可以大大简化容器的管理和运维工作,提高应用的可靠性和可扩展性。