NingG +

Docker 系列:Docker 实践

主要内容,几个方面:

1. 构建

1.1. base image

公司的 base image:

说明:

1.2. Dockerfile

问题

实践:采用 docker-maven-plugin 插件,将 Docker 的构建流程跟 Maven 的生命周期绑定

具体 pom 中配置:(https://company.io/common/parent)

                <plugin>
                    <groupId>com.spotify</groupId>
                    <artifactId>docker-maven-plugin</artifactId>
                    <version>1.0.0</version>
                    <configuration>
                        <imageName>${repo.docker}/${app.imagePath}</imageName>
                        <baseImage>${repo.docker}/infra/java:${java.version}</baseImage>
                        <workdir>/app</workdir>
                        <env>
                            <TZ>Asia/Shanghai</TZ>
                            <SPRING_APPLICATION_NAME>${project.artifactId}</SPRING_APPLICATION_NAME>
                        </env>
                        <entryPoint>["boot.sh", "${project.build.finalName}.${project.packaging}"]</entryPoint>
                        <resources>
                            <resource>
                                <targetPath>/app</targetPath>
                                <directory>${project.build.directory}</directory>
                                <include>${project.build.finalName}.${project.packaging}</include>
                            </resource>
                        </resources>
                        <runs>
                            <run>ln -snf /usr/share/zoneinfo/$TZ /etc/localtime</run>
                            <run>echo $TZ > /etc/timezone</run>
                        </runs>
                        <forceTags>true</forceTags>
                        <imageTags>
                            <imageTag>${project.version}</imageTag>
                        </imageTags>
                    </configuration>
                    <executions>
                        <execution>
                            <id>build-image</id>
                            <phase>package</phase>
                            <goals>
                                <goal>build</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>push-image</id>
                            <phase>deploy</phase>
                            <goals>
                                <goal>push</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <groupId>com.spotify</groupId>
                    <artifactId>dockerfile-maven-plugin</artifactId>
                    <version>1.4.0</version>
                    <configuration>
                        <repository>docker.company.io/${app.imagePath}</repository>
                        <tag>${project.version}</tag>
                        <buildArgs>
                            <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
                        </buildArgs>
                        <googleContainerRegistryEnabled>false</googleContainerRegistryEnabled>
                    </configuration>
                    <executions>
                        <execution>
                            <id>build-image</id>
                            <phase>package</phase>
                            <goals>
                                <goal>build</goal>
                            </goals>
                        </execution>
                        <execution>
                            <id>push-image</id>
                            <phase>deploy</phase>
                            <goals>
                                <goal>push</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>

上述插件的配置,生成 Dockerfile 内容如下:

FROM docker.company.io/common/alpine-oraclejdk8:1.2
ENV APP_HOME /opt
ENV SPRING_APPLICATION_NAME api ENV TZ Asia/Shanghai
WORKDIR /opt
ADD /opt/api.jar /opt/
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime RUN echo $TZ > /etc/timezone
ENTRYPOINT ["/opt/boot.sh", "/opt/api.jar"]

使用 docker-maven-plugin 的优缺点:

使用纯 Docker 的多阶段构建,可以作为一种替代方案:

FROM maven:3.5-jdk-8 AS build-env
ADD . /src
WORKDIR /src
RUN mvn clean package

FROM docker.company.io/common/alpine-oraclejdk8:1.2
ENV APP_HOME /opt
ENV SPRING_APPLICATION_NAME api ENV TZ Asia/Shanghai
WORKDIR /opt
COPY --from=build-env /src/target/ares-blade.jar /opt/ares-bla RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime
RUN echo $TZ > /etc/timezone
ENTRYPOINT ["/opt/boot.sh", "/opt/ares-blade.jar"]

纯 Docker 的多阶段构建,优点:

2. 运行

2.1. 资源限制

几个主要问题:

  1. 资源限制和什么有关?
  2. 我们做了资源限制么?
  3. 为什么我们做了一些资源限制 or 为什么没做一些资源限制?

2.1.1. 资源限制,跟什么有关

在「单机容器」场景,Docker 、Docker Compose:

在「集群」场景,Swarm、Kubernetes:

2.1.2. 资源限制,我们做了什么?

以 abacus/abacus-order 服务为例:https://git.company.io/abacus/abacus

内部实践的基本策略

Swarm 模式:(https://company.io/abacus/abacus/blob/master/docker-compose.prod.yml) resources.reservations 具体内容:

version: '3.3'
services:
  order:
    deploy:
      replicas: 12
      resources:
        reservations:
          cpus: '2'

Kubernetes 模式:(https://company.io/abacus/abacus/blob/master/abacus-prod.yaml) resources.requests 具体内容:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: abacus-order
spec:
  replicas: 12
  selector:
    matchLabels:
      app: abacus-order
  template:
    metadata:
      labels:
        app: abacus-order
    spec:
      containers:
      - name: abacus-order
        image: docker.company.io/abacus/abacus-order:2.0.18
        imagePullPolicy: Always
        resources:
          requests:
            cpu: "2000m"
        readinessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 35
          periodSeconds: 5
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 60
          periodSeconds: 5
        ports:
        - name: http
          containerPort: 8080
        env:
        - name: SPRING_APPLICATION_INSTANCE
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        envFrom:
        - configMapRef:
            name: abacus-env-vars
        volumeMounts:
        - name: config
          mountPath: /opt/config
        - name: logs
          mountPath: /opt/logs
      volumes:
      - name: config
        hostPath:
          path: /opt/config
      - name: logs
        hostPath:
          path: /opt/logs

疑问:

2.1.3. 为什么,没有限制内存

在 Docker 层面,限制「内存」:

JVM 层面,限制「内存」:

因此,建议 Docker 层面、JVM 层面,都设置「内存」限制

2.2. 网络

具体实践:

3. 集群

3.1. Swarm

3.1.1. Swarm 逻辑架构

具体逻辑架构:

3.1.2. Swarm 物理架构

Swarm 集群模式,物理架构:

其中,有一个很大的教训:

混布 Swarm Manager 的问题:

  1. 服务部署过程中, Swarm Manager 压力增大,会影响同一节点上的其他容器,容器一旦崩溃,会进一步增加 Swarm Manager 的压力

  2. 之前 Swarm Manager 同时支持 Swarm Worker 角色,导致 Swarm Manager 压力更大

3.2. Kubernetes

世纪之问:

为什么要从 Swarm 切换到 Kubernetes?从「容器化」走向「云原生」

术语简介:

Kubernetes 新特性:

同类文章:

微信搜索: 公众号 ningg ,即可联系我

Top