引言

Kubernetes(通常简称为K8s)已成为现代云原生应用部署和管理的事实标准。它最初由Google开发,现在由云原生计算基金会(CNCF)维护。Kubernetes提供了一个强大的平台,用于自动化容器化应用程序的部署、扩展和管理。无论你是初学者还是有经验的开发者,掌握Kubernetes都是提升职业竞争力的关键。本指南将从基础概念开始,逐步深入到高级主题和实战项目,帮助你构建完整的知识体系。

第一部分:Kubernetes基础概念

1.1 什么是Kubernetes?

Kubernetes是一个开源的容器编排系统,用于自动化应用程序的部署、扩展和管理。它最初由Google基于其内部系统Borg和Omega开发,现在已成为云原生生态系统的核心组件。

核心优势

  • 自动化部署:自动处理容器的部署、重启和替换。
  • 水平扩展:根据负载自动增加或减少容器实例。
  • 服务发现与负载均衡:自动分配IP地址和DNS名称,并提供负载均衡。
  • 存储编排:允许挂载各种存储系统,如本地存储、公有云存储等。
  • 自我修复:自动重启失败的容器,替换不健康的容器。

1.2 核心组件

Kubernetes集群由两个主要部分组成:控制平面(Control Plane)和工作节点(Worker Nodes)。

控制平面组件:

  • kube-apiserver:集群的前端,处理所有REST请求。
  • etcd:分布式键值存储,保存集群状态。
  • kube-scheduler:决定将Pod调度到哪个节点上。
  • kube-controller-manager:运行控制器进程,包括节点控制器、副本控制器等。

工作节点组件:

  • kubelet:在每个节点上运行,确保容器在Pod中运行。
  • kube-proxy:维护网络规则,实现服务发现和负载均衡。
  • 容器运行时:如Docker、containerd或CRI-O,负责运行容器。

1.3 基本对象

Kubernetes通过一系列对象来管理应用程序:

  • Pod:最小的可部署单元,包含一个或多个容器。
  • Service:定义一组Pod的访问策略,提供稳定的网络端点。
  • Deployment:管理Pod的副本集,支持滚动更新和回滚。
  • ConfigMap:存储非机密配置数据。
  • Secret:存储敏感数据,如密码、令牌。
  • Namespace:虚拟集群,用于资源隔离。

示例:一个简单的Pod定义文件(pod.yaml):

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx-container
    image: nginx:latest
    ports:
    - containerPort: 80

第二部分:环境搭建与入门实践

2.1 本地开发环境

对于初学者,建议使用本地环境进行学习。以下是几种常见的本地Kubernetes环境:

2.1.1 Minikube

Minikube是一个工具,可以在本地运行单节点Kubernetes集群。

安装步骤(以macOS为例):

# 安装Minikube
brew install minikube

# 启动集群
minikube start

# 验证集群状态
kubectl get nodes

2.1.2 Docker Desktop

Docker Desktop内置了Kubernetes支持,适合Windows和macOS用户。

启用步骤

  1. 打开Docker Desktop设置。
  2. 在“Kubernetes”选项卡中,勾选“Enable Kubernetes”。
  3. 点击“Apply & Restart”。

2.1.3 Kind

Kind(Kubernetes in Docker)是一个使用Docker容器运行Kubernetes集群的工具。

安装和使用

# 安装Kind
brew install kind

# 创建集群
kind create cluster --name my-cluster

# 验证集群
kubectl cluster-info --context kind-my-cluster

2.2 基本命令行工具

kubectl是Kubernetes的命令行工具,用于与集群交互。

常用命令

# 查看集群信息
kubectl cluster-info

# 查看节点
kubectl get nodes

# 查看所有Pod
kubectl get pods --all-namespaces

# 查看Pod详情
kubectl describe pod <pod-name>

# 创建资源
kubectl apply -f <file.yaml>

# 删除资源
kubectl delete -f <file.yaml>

2.3 第一个应用部署

让我们部署一个简单的Nginx应用。

步骤1:创建Deployment

# 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.21
        ports:
        - containerPort: 80

步骤2:应用配置

kubectl apply -f nginx-deployment.yaml

步骤3:创建Service

# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: NodePort  # 对于本地集群,使用NodePort或LoadBalancer

步骤4:应用Service配置

kubectl apply -f nginx-service.yaml

步骤5:访问应用

# 获取Service的NodePort
kubectl get service nginx-service

# 在浏览器中访问(Minikube)
minikube service nginx-service

# 或者使用kubectl port-forward
kubectl port-forward service/nginx-service 8080:80

第三部分:核心概念深入

3.1 Pod生命周期管理

Pod的生命周期包括创建、运行、终止等阶段。理解Pod的生命周期对于调试和优化应用至关重要。

Pod状态

  • Pending:Pod已被接受,但容器尚未创建。
  • Running:Pod已绑定到节点,所有容器已创建。
  • Succeeded:所有容器成功终止。
  • Failed:所有容器终止,至少一个容器失败。
  • Unknown:无法获取Pod状态。

示例:查看Pod状态

kubectl get pods -o wide

3.2 配置管理

3.2.1 ConfigMap

ConfigMap用于存储非机密配置数据,如配置文件、环境变量等。

创建ConfigMap

# 从字面值创建
kubectl create configmap my-config --from-literal=key1=value1 --from-literal=key2=value2

# 从文件创建
kubectl create configmap nginx-config --from-file=nginx.conf

在Pod中使用ConfigMap

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
  - name: nginx
    image: nginx
    env:
    - name: CONFIG_KEY
      valueFrom:
        configMapKeyRef:
          name: my-config
          key: key1
    volumeMounts:
    - name: config-volume
      mountPath: /etc/config
  volumes:
  - name: config-volume
    configMap:
      name: my-config

3.2.2 Secret

Secret用于存储敏感数据,如密码、API密钥等。

创建Secret

# 创建通用Secret
kubectl create secret generic my-secret --from-literal=username=admin --from-literal=password=secret123

# 创建TLS Secret
kubectl create secret tls my-tls-secret --cert=cert.pem --key=key.pem

在Pod中使用Secret

apiVersion: v1
kind: Pod
metadata:
  name: secret-pod
spec:
  containers:
  - name: nginx
    image: nginx
    env:
    - name: USERNAME
      valueFrom:
        secretKeyRef:
          name: my-secret
          key: username
    volumeMounts:
    - name: secret-volume
      mountPath: /etc/secret
      readOnly: true
  volumes:
  - name: secret-volume
    secret:
      secretName: my-secret

3.3 网络与服务发现

3.3.1 Service类型

Kubernetes Service提供多种类型:

  • ClusterIP:默认类型,仅在集群内部可访问。
  • NodePort:通过节点的静态端口暴露服务。
  • LoadBalancer:使用云提供商的负载均衡器。
  • ExternalName:将服务映射到外部DNS名称。

示例:创建ClusterIP Service

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
  type: ClusterIP

3.3.2 Ingress

Ingress用于管理外部访问集群中服务的路由规则,通常需要Ingress控制器(如Nginx Ingress、Traefik)。

安装Nginx Ingress控制器(Minikube):

minikube addons enable ingress

创建Ingress资源

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-service
            port:
              number: 80

第四部分:高级主题

4.1 持久化存储

Kubernetes支持多种存储卷类型,用于持久化数据。

4.1.1 PersistentVolume (PV) 和 PersistentVolumeClaim (PVC)

PV是集群中的存储资源,PVC是用户对存储的请求。

创建PV

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-volume
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /mnt/data

创建PVC

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-claim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

在Pod中使用PVC

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mycontainer
    image: nginx
    volumeMounts:
    - name: persistent-storage
      mountPath: /usr/share/nginx/html
  volumes:
  - name: persistent-storage
    persistentVolumeClaim:
      claimName: pvc-claim

4.1.2 动态卷供应

动态卷供应允许PVC自动创建PV,无需手动创建PV。这通常需要存储类(StorageClass)。

创建StorageClass

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs  # 根据云提供商调整
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
volumeBindingMode: Immediate

4.2 自动伸缩

Kubernetes支持水平Pod自动伸缩(HPA)和集群自动伸缩(Cluster Autoscaler)。

4.2.1 水平Pod自动伸缩(HPA)

HPA根据CPU使用率或其他指标自动调整Pod副本数。

创建HPA

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: hpa-example
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nginx-deployment
  minReplicas: 1
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

应用HPA

kubectl apply -f hpa.yaml

4.2.2 集群自动伸缩

集群自动伸缩器(Cluster Autoscaler)根据节点资源使用情况自动调整节点数量。这通常需要云提供商支持。

4.3 安全性

4.3.1 RBAC(基于角色的访问控制)

RBAC用于控制用户和应用程序对Kubernetes资源的访问权限。

创建Role和RoleBinding

# Role
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

# RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

4.3.2 Pod安全策略(PSP)和Pod安全标准(PSS)

Pod安全策略(PSP)已被弃用,现在推荐使用Pod安全标准(PSS)和Pod安全准入(PSA)。

应用Pod安全标准

apiVersion: v1
kind: Pod
metadata:
  name: restricted-pod
  labels:
    pod-security.kubernetes.io/enforce: restricted
spec:
  containers:
  - name: nginx
    image: nginx
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: ["ALL"]
      runAsNonRoot: true
      seccompProfile:
        type: RuntimeDefault

第五部分:实战项目

5.1 项目1:部署一个微服务应用

我们将部署一个简单的微服务应用,包含前端、后端和数据库。

5.1.1 应用架构

  • 前端:React应用,使用Nginx提供静态文件。
  • 后端:Node.js API服务。
  • 数据库:PostgreSQL。

5.1.2 部署步骤

步骤1:创建数据库Deployment和Service

# postgres-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:13
        env:
        - name: POSTGRES_DB
          value: myapp
        - name: POSTGRES_USER
          value: admin
        - name: POSTGRES_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: password
        ports:
        - containerPort: 5432
        volumeMounts:
        - name: postgres-storage
          mountPath: /var/lib/postgresql/data
      volumes:
      - name: postgres-storage
        persistentVolumeClaim:
          claimName: postgres-pvc
---
# postgres-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: postgres-service
spec:
  selector:
    app: postgres
  ports:
    - protocol: TCP
      port: 5432
      targetPort: 5432
  type: ClusterIP

步骤2:创建后端Deployment和Service

# backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: backend
        image: my-backend-image:latest  # 替换为你的镜像
        env:
        - name: DB_HOST
          value: postgres-service
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: db-secret
              key: password
        ports:
        - containerPort: 3000
---
# backend-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  selector:
    app: backend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: ClusterIP

步骤3:创建前端Deployment和Service

# frontend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 2
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: my-frontend-image:latest  # 替换为你的镜像
        ports:
        - containerPort: 80
---
# frontend-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  selector:
    app: frontend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP

步骤4:创建Ingress路由

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: myapp.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: frontend-service
            port:
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: backend-service
            port:
              number: 80

步骤5:创建Secret

kubectl create secret generic db-secret --from-literal=password=mysecretpassword

步骤6:应用所有配置

kubectl apply -f postgres-pvc.yaml
kubectl apply -f postgres-deployment.yaml
kubectl apply -f postgres-service.yaml
kubectl apply -f backend-deployment.yaml
kubectl apply -f backend-service.yaml
kubectl apply -f frontend-deployment.yaml
kubectl apply -f frontend-service.yaml
kubectl apply -f ingress.yaml

5.2 项目2:CI/CD流水线集成

使用GitOps工具(如ArgoCD)和CI工具(如Jenkins或GitHub Actions)实现自动化部署。

5.2.1 安装ArgoCD

# 创建ArgoCD命名空间
kubectl create namespace argocd

# 安装ArgoCD
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 获取初始密码
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d

5.2.2 创建Git仓库

创建一个Git仓库,包含Kubernetes清单文件。

目录结构

k8s-manifests/
├── base/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── ingress.yaml
└── overlays/
    ├── dev/
    │   └── kustomization.yaml
    └── prod/
        └── kustomization.yaml

示例base/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        ports:
        - containerPort: 80

5.2.3 配置ArgoCD Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/yourusername/k8s-manifests.git
    targetRevision: HEAD
    path: overlays/dev
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

第六部分:最佳实践与优化

6.1 资源管理

6.1.1 资源请求和限制

为Pod设置资源请求和限制,确保公平调度和避免资源耗尽。

示例

apiVersion: v1
kind: Pod
metadata:
  name: resource-pod
spec:
  containers:
  - name: app
    image: myapp
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

6.1.2 命名空间资源配额

使用ResourceQuota限制命名空间的资源使用。

示例

apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-resources
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

6.2 监控与日志

6.2.1 Prometheus和Grafana

Prometheus用于监控,Grafana用于可视化。

安装Prometheus和Grafana(使用Helm):

# 添加Helm仓库
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

# 安装kube-prometheus-stack
helm install prometheus prometheus-community/kube-prometheus-stack

配置Grafana仪表板

  1. 访问Grafana(默认用户:admin,密码:prom-operator)。
  2. 添加Prometheus数据源。
  3. 导入Kubernetes仪表板(ID:3119)。

6.2.2 日志收集

使用EFK(Elasticsearch, Fluentd, Kibana)或Loki收集日志。

安装Loki和Promtail(使用Helm):

helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm install loki grafana/loki-stack

6.3 高可用性与灾难恢复

6.3.1 多集群部署

使用Kubernetes联邦(KubeFed)或云提供商的多集群解决方案。

6.3.2 备份与恢复

使用Velero进行备份和恢复。

安装Velero

# 安装Velero CLI
curl -L https://github.com/vmware-tanzu/velero/releases/download/v1.9.0/velero-v1.9.0-linux-amd64.tar.gz | tar -xzv
sudo mv velero /usr/local/bin/

# 创建备份
velero backup create my-backup --include-namespaces default

第七部分:学习资源与社区

7.1 官方文档

7.2 在线课程

7.3 书籍推荐

  • 《Kubernetes权威指南:从Docker到Kubernetes实践全接触》
  • 《Kubernetes in Action》
  • 《Kubernetes Patterns》

7.4 社区与论坛

结语

Kubernetes是一个强大但复杂的系统,掌握它需要时间和实践。本指南从基础概念开始,逐步深入到高级主题和实战项目,希望能为你的学习之旅提供清晰的路径。记住,持续学习和实践是掌握Kubernetes的关键。加入社区,参与开源项目,不断挑战自己,你将逐步成为Kubernetes专家。

下一步行动

  1. 在本地环境部署一个简单的应用。
  2. 尝试使用Helm管理应用。
  3. 探索Kubernetes生态系统的其他工具,如Istio、Knative等。
  4. 参与Kubernetes社区,贡献代码或文档。

祝你学习愉快!