Kubernetes容器编排部署实战:从集群初始化到应用滚动更新全流程

Docker镜像构建规范与多阶段构建优化

DevOps实践的核心在于将应用部署、扩缩容、故障恢复全流程自动化。Kubernetes容器编排已成为这一领域的事实标准,从Docker镜像构建到K8s集群运维,每个环节都需要精确配置。本文以一个Java Spring Boot微服务项目为例,覆盖完整的CI/CD流水线和监控告警体系搭建。

Docker镜像质量直接影响Kubernetes容器编排的部署效率和运行稳定性。生产环境的镜像构建需要遵循几个原则:镜像体积最小化、分层缓存利用最大化、构建过程可重复。多阶段构建是控制镜像体积最有效的手段。

多阶段Dockerfile示例:

# ---- 编译阶段 ----
FROM maven:3.9-eclipse-temurin-17 AS builder
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline -B
COPY src ./src
RUN mvn package -DskipTests -B

# ---- 运行阶段 ----
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /build/target/app.jar /app/app.jar
RUN addgroup -S appgrp && adduser -S appuser -G appgrp
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
  CMD wget -qO- http://localhost:8080/actuator/health | grep -q UP || exit 1
ENTRYPOINT ["java", "-XX:MaxRAMPercentage=75.0", "-jar", "/app/app.jar"]

编译阶段用完整的Maven镜像,运行阶段只装JRE,最终镜像体积从800MB压缩到约180MB。COPY pom.xml单独放一层是为了利用Docker分层缓存——pom不变时依赖下载层直接命中缓存,不会重复执行。

Kubernetes集群初始化与网络插件配置

集群搭建以kubeadm方式为例,测试环境使用3台机器(1 master + 2 worker)。所有节点前置配置:

# 关闭swap
swapoff -a && sed -i '/swap/d' /etc/fstab

# 内核参数调整
cat > /etc/sysctl.d/k8s.conf << 'EOF'
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system

# 安装容器运行时(containerd)
yum install -y containerd.io
containerd config default > /etc/containerd/config.toml
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
systemctl enable containerd --now

# 安装kubeadm、kubelet、kubectl
cat > /etc/yum.repos.d/kubernetes.repo << 'EOF'
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm/
enabled=1
gpgcheck=0
EOF
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet

Master节点初始化:

kubeadm init \
  --apiserver-advertise-address=192.168.30.10 \
  --pod-network-cidr=10.244.0.0/16 \
  --image-repository=registry.aliyuncs.com/google_containers \
  --kubernetes-version=v1.30.0

mkdir -p $HOME/.kube
cp /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

安装Calico网络插件:

kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27/manifests/tigera-operator.yaml
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.27/manifests/custom-resources.yaml

# 等待Calico Pod就绪
kubectl get pods -n calico-system -w

Worker节点加入集群:

# 在master上获取加入命令
kubeadm token create --print-join-command

# 在worker节点执行返回的kubeadm join命令
kubeadm join 192.168.30.10:6443 --token xxx --discovery-token-ca-cert-hash sha256:xxx

Deployment与Service部署配置

应用部署YAML(deployment.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: order-service
  namespace: production
  labels:
    app: order-service
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  selector:
    matchLabels:
      app: order-service
  template:
    metadata:
      labels:
        app: order-service
    spec:
      containers:
      - name: order-service
        image: registry.example.com/order-service:v2.1.0
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
          limits:
            cpu: 1000m
            memory: 1Gi
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"
        - name: JAVA_OPTS
          value: "-XX:MaxRAMPercentage=75.0 -XX:+UseG1GC"
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 20
          periodSeconds: 5
          failureThreshold: 3
        lifecycle:
          preStop:
            exec:
              command: ["sh", "-c", "sleep 15"]
      terminationGracePeriodSeconds: 60
---
apiVersion: v1
kind: Service
metadata:
  name: order-service
  namespace: production
spec:
  selector:
    app: order-service
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
  type: ClusterIP

几个关键配置项的实战要点:

滚动更新策略:maxUnavailable: 1和maxSurge: 1的组合意味着更新过程中始终保持至少2个可用Pod,同时最多多出1个Pod。这个配置在3副本场景下既保证可用性又控制资源消耗。

优雅停机:preStop钩子中的sleep 15配合terminationGracePeriodSeconds: 60。Kubernetes停止Pod时先发SIGTERM信号,但Service的endpoint更新有传播延迟。sleep 15让Pod在收到SIGTERM后继续服务15秒,等endpoint更新传播完毕,避免请求打到正在关闭的Pod上。

探针配置:livenessProbe判断容器是否需要重启,readinessProbe判断容器是否可以接收流量。两者路径分开——liveness检查应用进程存活,readiness检查依赖是否ready。

CI/CD流水线自动化部署

以GitLab CI为例,配置从代码提交到自动部署的流水线(.gitlab-ci.yml):

stages:
  - build
  - test
  - package
  - deploy

variables:
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA

build:
  stage: build
  image: maven:3.9-eclipse-temurin-17
  script:
    - mvn package -DskipTests -B
  artifacts:
    paths:
      - target/*.jar
    expire_in: 1 hour

test:
  stage: test
  image: maven:3.9-eclipse-temurin-17
  script:
    - mvn test -B
  only:
    - main
    - develop

package:
  stage: package
  image: docker:24
  services:
    - docker:24-dind
  script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG
    - docker tag $IMAGE_TAG $CI_REGISTRY_IMAGE:latest
    - docker push $CI_REGISTRY_IMAGE:latest
  only:
    - main

deploy_staging:
  stage: deploy
  image: bitnami/kubectl:1.30
  script:
    - kubectl config use-context staging
    - kubectl set image deployment/order-service
      order-service=$IMAGE_TAG -n staging
    - kubectl rollout status deployment/order-service -n staging
  environment:
    name: staging
  only:
    - main

流水线拆分为build、test、package、deploy四个阶段,每个阶段在独立容器中执行。package阶段使用Docker-in-Docker构建镜像并推送到Registry。deploy阶段通过kubectl set image触发Kubernetes滚动更新,rollout status命令阻塞直到更新完成或超时。

监控告警体系搭建

监控告警是SRE稳定性工程的基础设施。推荐使用Prometheus + Grafana + AlertManager组合:

# 监控命名空间
kubectl create namespace monitoring

# 通过Helm部署Prometheus Stack
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install kube-prometheus-stack prometheus-community/kube-prometheus-stack \
  -n monitoring \
  --set grafana.service.type=NodePort \
  --set grafana.service.nodePort=30300 \
  --set prometheus.prometheusSpec.retention=15d \
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.storageClassName=standard \
  --set prometheus.prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage=50Gi

关键告警规则(PrometheusRule):

apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: app-alerts
  namespace: monitoring
spec:
  groups:
  - name: application.rules
    rules:
    - alert: PodCrashLooping
      expr: increase(kube_pod_container_status_restarts_total[1h]) > 5
      for: 10m
      labels:
        severity: critical
      annotations:
        summary: "Pod {{ $labels.pod }} 频繁重启"
        description: "命名空间 {{ $labels.namespace }} 中的 Pod {{ $labels.pod }} 在1小时内重启超过5次"

    - alert: HighCPUUsage
      expr: |
        sum(rate(container_cpu_usage_seconds_total{container!=""}[5m])) by (pod, namespace) /
        sum(kube_pod_container_resource_limits{resource="cpu"}) by (pod, namespace) > 0.85
      for: 10m
      labels:
        severity: warning
      annotations:
        summary: "Pod {{ $labels.pod }} CPU使用率超过85%"

    - alert: HighMemoryUsage
      expr: |
        sum(container_memory_working_set_bytes{container!=""}) by (pod, namespace) /
        sum(kube_pod_container_resource_limits{resource="memory"}) by (pod, namespace) > 0.90
      for: 5m
      labels:
        severity: critical
      annotations:
        summary: "Pod {{ $labels.pod }} 内存使用率超过90%"

    - alert: ServiceUnavailable
      expr: kube_endpoint_address_available / kube_endpoint_address_not_available < 1
      for: 2m
      labels:
        severity: critical
      annotations:
        summary: "Service {{ $labels.service }} 有端点不可用"

故障应急响应与混沌工程实践

日志分析是故障应急的第一信息源。在Kubernetes环境中,集中化日志收集方案用Fluent Bit + Elasticsearch + Kibana:

# Fluent Bit DaemonSet部署,收集所有节点容器日志
kubectl apply -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/output/elasticsearch/fluent-bit-configmap.yaml
kubectl apply -f https://raw.githubusercontent.com/fluent/fluent-bit-kubernetes-logging/master/output/elasticsearch/fluent-bit-ds.yaml

混沌工程用于主动验证高可用能力。使用Chaos Mesh向集群注入故障:

apiVersion: chaos-mesh.org/v1alpha1
kind: PodChaos
metadata:
  name: kill-random-pod
  namespace: chaos-testing
spec:
  action: pod-kill
  mode: one
  selector:
    namespaces:
      - production
    labelSelectors:
      "app": "order-service"
  scheduler:
    cron: "@every 30m"

这个配置每30分钟随机杀死一个order-service Pod,验证Kubernetes的自愈机制和业务降级逻辑是否生效。混沌工程实验的目的是在故障真实发生前暴露系统弱点,而不是制造混乱。每次实验需要明确假设、可控范围和回退方案。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-rong-qi-bian-pai-bu-shu-shi-zhan-cong-ji-qun-chu/

(0)
小编小编
上一篇 18小时前
下一篇 18小时前

相关推荐

Kubernetes容器编排部署实战:从集群初始化到应用滚动更新全流程

Kubernetes容器编排已成为云原生架构的事实标准。本文以一个Java Web应用的部署为例,覆盖集群初始化、容器镜像构建、YAML清单编写、滚动更新和故障应急响应全流程,适用于DevOps实践和SRE稳定性工程场景。

Kubernetes集群初始化准备

使用kubeadm搭建三节点集群(1 Master + 2 Worker)。系统使用Ubuntu 22.04 LTS,containerd作为容器运行时。Docker自动化部署在K8s环境中通过containerd实现,但开发环境仍保留Docker用于镜像构建。

# 所有节点执行:关闭swap
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab

# 加载内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

modprobe overlay
modprobe br_netfilter

# 设置内核参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sysctl --system
# 安装containerd
apt-get update && apt-get install -y containerd

# 生成默认配置
containerd config default | sudo tee /etc/containerd/config.toml

# 修改SystemdCgroup为true(K8s 1.25+要求)
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

systemctl restart containerd
systemctl enable containerd
# 安装kubeadm, kubelet, kubectl
apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | \
  sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | \
  sudo tee /etc/apt/sources.list.d/kubernetes.list

apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl

初始化Master节点与Worker加入

# 在Master节点初始化集群
kubeadm init \
  --apiserver-advertise-address=192.168.1.10 \
  --pod-network-cidr=10.244.0.0/16

# 配置kubectl
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

# 安装Calico网络插件
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.0/manifests/calico.yaml
# 在Worker节点执行(初始化时输出的命令)
kubeadm join 192.168.1.10:6443 --token xxxxxx.xxxxxxxxxxxxxxxx \
  --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# 在Master验证节点状态
kubectl get nodes
# NAME           STATUS   ROLES           AGE   VERSION
# k8s-master     Ready    control-plane   10m   v1.30.0
# k8s-worker-1   Ready    <none>          8m    v1.30.0
# k8s-worker-2   Ready    <none>          6m    v1.30.0

容器镜像构建与推送

以Spring Boot应用为例,构建Docker镜像并推送到私有镜像仓库。

# Dockerfile
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY target/app.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar", "--server.port=8080"]
# 构建并推送镜像
docker build -t 192.168.1.100:5000/webapp:v1.0.0 .
docker push 192.168.1.100:5000/webapp:v1.0.0

编写Kubernetes部署清单

一个完整的部署需要Deployment、Service和ConfigMap。以下是生产级别的YAML清单,包含资源限制、健康检查和优雅关闭配置。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp
  namespace: production
  labels:
    app: webapp
spec:
  replicas: 3
  selector:
    matchLabels:
      app: webapp
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: webapp
    spec:
      terminationGracePeriodSeconds: 60
      containers:
      - name: webapp
        image: 192.168.1.100:5000/webapp:v1.0.0
        ports:
        - containerPort: 8080
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
          limits:
            cpu: 1000m
            memory: 1024Mi
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
          failureThreshold: 3
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 5
        lifecycle:
          preStop:
            exec:
              command: ["sh", "-c", "sleep 15"]
---
apiVersion: v1
kind: Service
metadata:
  name: webapp-svc
  namespace: production
spec:
  selector:
    app: webapp
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP
# 部署应用
kubectl apply -f deploy.yaml

# 验证Pod状态
kubectl get pods -n production -l app=webapp
kubectl describe deployment webapp -n production

滚动更新与回滚操作

CI/CD流水线集成K8s时,滚动更新是最常见的发布方式。推送新镜像后更新Deployment:

# 方式一:直接更新镜像
kubectl set image deployment/webapp \
  webapp=192.168.1.100:5000/webapp:v1.1.0 -n production

# 监控滚动更新进度
kubectl rollout status deployment/webapp -n production
# 输出: deployment "webapp" successfully rolled out

# 如果新版本有问题,立即回滚
kubectl rollout undo deployment/webapp -n production

# 回滚到指定历史版本
kubectl rollout history deployment/webapp -n production
kubectl rollout undo deployment/webapp -n production --to-revision=2
# rollout过程中的关键参数解释:
# maxSurge=1: 旧Pod全部存活时,最多多启动1个新Pod
# maxUnavailable=0: 始终保证3个Pod可用,不中断服务
# preStop sleep 15: 给Service 15秒时间摘除流量

故障应急响应:Pod异常诊断

混沌工程实践中,模拟Pod故障是验证系统韧性的关键手段。以下是常见故障的诊断方法:

# 1. Pod处于Pending状态
kubectl describe pod <pod-name> -n production | tail -20
# 常见原因:资源不足、节点亲和性不满足、PVC未绑定
# 解决:调整resources.requests或扩容节点

# 2. Pod处于CrashLoopBackOff
kubectl logs <pod-name> -n production --previous
# --previous查看上一次崩溃的日志
# 常见原因:应用启动失败、配置错误、依赖服务未就绪

# 3. Pod处于ImagePullBackOff
kubectl describe pod <pod-name> -n production
# 常见原因:镜像地址错误、仓库认证失败
# 解决:配置imagePullSecrets或检查镜像地址

# 4. 服务无法访问
kubectl get endpoints webapp-svc -n production
# 如果ENDPOINTS为空,说明没有就绪的Pod
# 检查readinessProbe配置是否正确

监控告警体系搭建要点

K8s环境下推荐使用Prometheus配合Grafana搭建监控告警体系。日志分析使用Loki或ELK。核心监控指标:

# 必须配置的告警规则(PrometheusRule)
groups:
- name: k8s-alerts
  rules:
  - alert: PodCrashLooping
    expr: rate(kube_pod_container_status_restarts_total[15m]) > 0
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "Pod频繁重启"

  - alert: NodeHighCpu
    expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
    for: 10m
    labels:
      severity: warning
    annotations:
      summary: "节点CPU使用率超过80%"

  - alert: DeploymentReplicasMismatch
    expr: kube_deployment_status_replicas_available != kube_deployment_spec_replicas
    for: 10m
    labels:
      severity: critical
    annotations:
      summary: "Deployment可用副本数不匹配"

Kubernetes容器编排不是简单的容器调度平台,而是包含服务发现、负载均衡、自愈、滚动更新在内的完整运维体系。SRE稳定性工程的核心是让系统在故障发生时自动恢复,而非人工介入。从集群初始化到滚动更新到监控告警,每个环节都需要可追溯、可回滚的自动化流程。

原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/kubernetes-rong-qi-bian-pai-bu-shu-shi-zhan-cong-ji-qun-chu/

(0)
小编小编
上一篇 19小时前
下一篇 19小时前

相关推荐