Docker+K8s 微服务部署与运维实战指南
基于 Docker 和 Kubernetes 部署 Java 微服务的全流程,涵盖环境准备、Dockerfile 优化、Harbor 镜像仓库搭建、K8s 集群初始化、微服务 YAML 配置及监控日志方案。通过实战步骤与避坑指南,帮助开发者实现微服务的容器化部署与自动化运维,确保生产环境的稳定性与可扩展性。

基于 Docker 和 Kubernetes 部署 Java 微服务的全流程,涵盖环境准备、Dockerfile 优化、Harbor 镜像仓库搭建、K8s 集群初始化、微服务 YAML 配置及监控日志方案。通过实战步骤与避坑指南,帮助开发者实现微服务的容器化部署与自动化运维,确保生产环境的稳定性与可扩展性。

微服务部署常面临环境一致性和运维复杂度挑战。开发环境运行正常,测试和生产环境却可能出现配置不一致、端口冲突等问题。Docker+K8s 组合能有效解决这些痛点。本文从 Java 开发视角,介绍微服务容器化与 K8s 编排的全流程,涵盖环境搭建到生产运维的实战步骤。
核心原因有三点:
避坑提醒:很多中小团队会觉得 K8s 太重,其实现在 kubeadm 搭建集群已经很简单。如果团队规模特别小,也可以先从 Docker Compose 入手,但长远来看,K8s 是趋势。
| 节点角色 | 数量 | 配置要求 | 操作系统 |
|---|---|---|---|
| Master 节点 | 1 | 4 核 8G,50G 硬盘 | CentOS 7.9 / Ubuntu 20.04 |
| Worker 节点 | 2+ | 4 核 8G,100G 硬盘 | CentOS 7.9 / Ubuntu 20.04 |
| 镜像仓库节点 | 1 | 2 核 4G,100G 硬盘 | CentOS 7.9 / Ubuntu 20.04 |
# 关闭防火墙
systemctl stop firewalld
systemctl disable firewalld
# 关闭 SELinux
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
EOF
sysctl --system
# 安装依赖
yum install -y yum-utils device-mapper-persistent-data lvm2
# 配置 Docker 镜像源
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 安装指定版本 Docker
yum install -y docker-ce-20.10.24 docker-ce-cli-20.10.24 containerd.io
# 启动 Docker 并设置开机自启
systemctl start docker
systemctl enable docker
# 配置 Docker 镜像加速
cat > /etc/docker/daemon.json << EOF
{
"registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"]
}
EOF
systemctl daemon-reload
systemctl restart docker
避坑提醒:Docker 的 cgroup 驱动必须设置为 systemd,否则 K8s 初始化会报错。
以一个标准的 Spring Boot 微服务为例,Dockerfile 放在项目根目录:
# 第一阶段:构建应用
FROM maven:3.8.8-openjdk-11 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn clean package -DskipTests
# 第二阶段:运行应用
FROM openjdk:11-jre-slim
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
ENV JAVA_OPTS="-Xms512m -Xmx512m -XX:+UseG1GC -XX:MaxGCPauseMillis=200"
EXPOSE 8080
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]
关键优化点:分层构建减小镜像体积;JVM 参数优化避免 OOM;入口命令使用 exec 格式。
docker build -t harbor.example.com/microservice/user-service:1.0.0 .
curl -L "https://github.com/docker/compose/releases/download/v2.20.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
wget https://github.com/goharbor/harbor/releases/download/v2.5.3/harbor-offline-installer-v2.5.3.tgz
tar -zxvf harbor-offline-installer-v2.5.3.tgz -C /usr/local/
cd /usr/local/harbor
cp harbor.yml.tmpl harbor.yml
vi harbor.yml
关键配置修改:
hostname: harbor.example.com
http:
port: 80
harbor_admin_password: Harbor12345
data_volume: /data/harbor
./install.sh
docker-compose -f /usr/local/harbor/docker-compose.yml up -d
docker login harbor.example.com
docker push harbor.example.com/microservice/user-service:1.0.0
docker logout harbor.example.com
避坑提醒:如果 Harbor 用 HTTP 协议,需要在所有 K8s 节点的 Docker 配置中添加
"insecure-registries": ["harbor.example.com"]。
cat > /etc/yum.repos.d/kubernetes.repo << EOF
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-$basearch/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
exclude=kubelet kubeadm kubectl
EOF
yum install -y kubelet-1.24.10 kubeadm-1.24.10 kubectl-1.24.10 --disableexcludes=kubernetes
systemctl start kubelet
systemctl enable kubelet
kubeadm init \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.24.10 \
--pod-network-cidr=10.244.0.0/16 \
--service-cidr=10.96.0.0/12
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
kubectl get nodes
kubectl apply -f https://docs.projectcalico.org/v3.24/manifests/calico.yaml
kubectl get pods -n kube-system
在所有 Worker 节点执行 Master 初始化时输出的 kubeadm join 命令。
kubectl get nodes
kubectl get pods -n kube-system
apiVersion: apps/v1
kind: Deployment
metadata:
name: user-service
namespace: microservice
spec:
replicas: 2
selector:
matchLabels:
app: user-service
template:
metadata:
labels:
app: user-service
spec:
containers:
- name: user-service
image: harbor.example.com/microservice/user-service:1.0.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8080
resources:
requests:
cpu: "500m"
memory: "512Mi"
limits:
cpu: "1000m"
memory: "1024Mi"
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
initialDelaySeconds: 60
apiVersion: v1
kind: Service
metadata:
name: user-service
namespace: microservice
spec:
selector:
app: user-service
ports:
- port: 80
targetPort: 8080
type: ClusterIP
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: microservice-ingress
namespace: microservice
annotations:
kubernetes.io/ingress.class: "nginx"
spec:
rules:
- host: user.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
kubectl create namespace microservice
kubectl apply -f Deployment.yaml
kubectl apply -f Service.yaml
kubectl apply -f Ingress.yaml
kubectl get pods -n microservice
kubectl get svc -n microservice
kubectl get ingress -n microservice
curl http://user-service.microservice.svc.cluster.local:80/health
curl http://user.example.com/health
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install prometheus prometheus-community/prometheus -n monitoring --create-namespace
helm repo add grafana https://grafana.github.io/helm-charts
helm install grafana grafana/grafana -n monitoring
在 pom.xml 中添加依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
在 application-prod.yml 中配置:
management:
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
tags:
application: user-service
endpoint:
health:
probes:
enabled: true
show-details: always
scrape_configs:
- job_name: 'microservice'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_label_app]
action: keep
regex: .*service
- source_labels: [__meta_kubernetes_pod_container_port_number]
action: keep
regex: 8080
kubectl get secret grafana -n monitoring -o jsonpath="{.data.admin-password}" | base64 --decode
helm repo add elastic https://helm.elastic.co
helm install elasticsearch elastic/elasticsearch -n logging --create-namespace
helm install logstash elastic/logstash -n logging
helm install kibana elastic/kibana -n logging
在 logback-spring.xml 中配置:
<appender name="FILE">
<file>/var/log/user-service.log</file>
<rollingPolicy>
<fileNamePattern>/var/log/user-service.%d{yyyy-MM-dd}.log</fileNamePattern>
<maxHistory>7</maxHistory>
</rollingPolicy>
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="FILE" />
</root>
filebeat.inputs:
- type: filestream
paths:
- /var/log/*.log
processors:
- add_kubernetes_metadata:
host: ${NODE_NAME}
output.elasticsearch:
hosts: ["elasticsearch-master:9200"]
kubectl set image deployment/user-service user-service=harbor.example.com/microservice/user-service:1.0.1 -n microservice
kubectl rollout status deployment/user-service -n microservice
kubectl rollout history deployment/user-service -n microservice
kubectl rollout undo deployment/user-service -n microservice
kubectl rollout undo deployment/user-service --to-revision=1 -n microservice
Docker+K8s 已经成为微服务部署的标准方案。后续可以进一步优化的方向包括集成 CI/CD、引入 Istio 服务网格、以及使用 PV/PVC 机制处理持久化存储。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online