前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >7. 死磕 k8s系列之maven安装docker插件

7. 死磕 k8s系列之maven安装docker插件

作者头像
彤哥
发布2020-02-11 09:54:30
1.5K0
发布2020-02-11 09:54:30
举报
文章被收录于专栏:彤哥读源码彤哥读源码

简介

本章我们将学习如何在maven中集成docker插件,通过maven直接打包docker镜像并将之推送到docker仓库中。

前提

  • 必须已安装docker客户端

创建springboot应用

我们这里使用springboot快速创建一个应用。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.tt.k8s</groupId>
    <artifactId>docker-test</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>

    <build>
        <!-- 生成jar包的名称 -->
        <finalName>${project.artifactId}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

注意,这里生成的jar包去除掉版本号。

HelloController.java

@RestController
public class HelloController {

    @GetMapping("/hello/{name}")
    public String hello(@PathVariable String name) {
        return "Hello " + name + "!";
    }
}

本地启动,浏览器输入 http://localhost:8080/hello/Andy后成功打印出 HelloAndy!说明应用没问题。

编写Dockerfile文件

在工程的主目录创建Dockerfile文件,并输入以下内容:

#pull base image
FROM openjdk:8-jdk-alpine

#maintainer
MAINTAINER andy

#expose port 8080
EXPOSE 8080

#default command
CMD java -jar /data/docker-test.jar

#copy docker-test.jar to docker image
ADD ./target/docker-test.jar /data/docker-test.jar

FROM,表示基础镜像,这里我们选择一个openjdk的基础镜像。

MAINTAINER,表示作者,随便写。

EXPOSE,暴露的端口。

ADD,表示将target目录下的jar包拷贝到镜像中的对应目录,前一个目录是执行docker build所在的机器,后一个目录是镜像中的目录。

CMD,表示容器启动执行的命令,可以在启动镜像的时候被覆盖。

ENTRYPOINT,表示容器启动的进入点,不可以被覆盖。

CMD和ENTRYPOINT比较容易混淆,这里略作区分。

比如,按照上面Dockerfile的配置:

(1)如果执行 docker run test,则会执行CMD后的命令 java-jar/data/docker-test.jar

(2)如果执行 docker run test/bin/bash,则不会执行CMD后的命令,相当于被覆盖了;

如果把上面配置中的CMD换成ENTRYPOINT:

ENTRYPOINT java -jar /data/docker-test.jar

(1)如果执行 docker run test,则会执行ENTRYPOINT后的命令 java-jar/data/docker-test.jar

(2)如果执行 docker run test/bin/bash,则会执行 java-jar/data/docker-test.jar/bin/bash,这时候 /bin/bash相当于变成ENTRYPOINT后面命令的参数了;

总之,ENTRYPOINT后面的命令是一定会执行的,但CMD却不一定。

集成时间插件

Maven本身是包含时间插件的,但是那个插件取出来的时间为UTC时间,比中国的时间慢8个小时,看着很不爽。

所以,这里我们集成一个时间插件,用于后面自动生成镜像的版本号。

pom.xml中加入以下plugin:

<!--生成当前时间,maven自带的是UTC时间,不符合要求-->
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>buildnumber-maven-plugin</artifactId>
    <version>1.4</version>
    <configuration>
        <timestampFormat>yyyyMMddHHmmss</timestampFormat>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>create-timestamp</goal>
            </goals>
        </execution>
    </executions>
    <inherited>false</inherited>
</plugin>

集成dockerfile插件

现在网上流传的docker插件有两个版本,分别是 docker-maven-plugindockerfile-maven-plugin

它们都是同一个作者写的,作者已经明确声明,前者已经被废弃,所以我们这里使用dockerfile插件。

pom.xml中加入以下plugin:

<!-- dockerfile插件 -->
<plugin>
    <groupId>com.spotify</groupId>
    <artifactId>dockerfile-maven-plugin</artifactId>
    <version>1.4.10</version>
    <executions>
        <execution>
            <id>default</id>
            <goals>
                <!--如果package时不想用docker打包,就注释掉这个goal-->
                <goal>build</goal>
                <goal>push</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <!-- Dockerfile -->
        <dockerfile>Dockerfile</dockerfile>
        <username>admin</username>
        <password>Harbor12345</password>
        <!-- 注意这里的前缀填写前面我们harbor的地址 -->
        <repository>core.harbor.domain/test/${project.artifactId}</repository>
        <tag>${timestamp}</tag>
    </configuration>
</plugin>

注意,这里填写我们前面安装的harbor的用户名、密码和仓库地址。

构建并推送到远程仓库

上面的准备工作做完了,在IDEA的右侧找到maven,点击输入命令的那个框,输入以下命令,点击执行,即可构建/推送一步完成。

clean package dockerfile:build dockerfile:push

如果不出意外,你是怎么都不会成功的。

无限踩坑过程

cannot conn to localhost:2375

如果报连接不上localhost:2375,尝试把IDEA重启下,因为docker安装的过程中会修改环境变量DOCKER_HOST,IDEA好像没有感知到,重启下即可。

如果是使用DeskTop方式安装的docker客户端,需要打个勾,自己百度下这个错误就能查到答案了。

lookup core.harbor.domain on 10.0.2.3:53: no such host

这是因为我们使用的是toolbox安装的docker,而实际上docker的操作是在virtual box虚拟机中,所以这里也要修改虚拟机中的hosts,添加core.harbor.domain域名的映射。

打开桌面上的图标 OracleVMVirtualBox,双击其中正在运行的虚拟机default或者点击上方的“显示”按钮,进入虚拟机内部。

注,这里操作窗口比较小且不可滚动,可以使用XSHELL等工具进入,ip固定为192.168.99.100,用户名为docker,密码为tcuser。

进入后找到/etc/hosts文件添加一行:

# 任意worker节点的ip
xx.xx.xx.xx core.harbor.domain

然后,你会发现没有修改权限,使用 sudo su切换到root,再次修改保存。

再次执行maven构建/推送命令,又来个新错误。

x509: certificate signed by unknown authority

这是因为docker客户端没有配置docker仓库的证书。

打开harbor,选择项目test,点击“镜像仓库”标签页,点击“注册证书”。

在虚拟机的 /etc/docker/certs.d/core.harbor.domain/目录下新建 ca.crt文件,并把刚才下载的证书的内容拷贝进去,保存退出。

root@default:/home/docker# mkdir -p /etc/docker/certs.d/core.harbor.domain/
root@default:/home/docker# cd /etc/docker/certs.d/core.harbor.domain/
root@default:/etc/docker/certs.d/core.harbor.domain# vi ca.crt
root@default:/etc/docker/certs.d/core.harbor.domain# ls
ca.crt

注,这里无法直接使用上传命令,使用拷贝粘贴的方式更快捷。

再次执行maven构建/推送命令,又来个新错误。

denied: requested access to the resource is denied

这是因为docker客户端没有登录到我们的私仓。

虽然,上面我们maven插件中配置了用户名/密码,但是似乎不生效。

打开docker客户端(命令行),登录到远程仓库:

$ docker login core.harbor.domain
Authenticating with existing credentials...
Stored credentials invalid or expired
Username (alan): admin
Password:
WARNING! Your password will be stored unencrypted in C:\Users\01384359\.docker\config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

再次执行maven构建/推送命令,又来个新错误。

413 Request Entity Too Large

报了个413错误,请求体太大,查看镜像的大小大概有122M的样子。

出现这个错误,一般是nginx上传文件时做了限制,这时候我们想一下,我们的harbor是通过Ingress访问的,Ingress是需要一个Ingress Controller的,还记得我们当时装的nginx ingress吗?对了,这里使用的就是nginx。

这时候我们通过kuboard,打开任意一个nginx ingress的web版ssh。

点击终端进入docker容器内部,找到harbor的配置文件,你肯定会问我怎么知道harbor的配置文件在这里,我只能说这只能靠经验了。

root@nginx-ingress-55dfk:/# cd /etc/nginx/conf.d/
root@nginx-ingress-55dfk:/etc/nginx/conf.d# ls
harbor-harbor-harbor-ingress.conf  kube-system-kuboard.conf
root@nginx-ingress-55dfk:/etc/nginx/conf.d# cat harbor-harbor-harbor-ingress.conf
# 省略...
        location / {


                proxy_http_version 1.1;


                proxy_connect_timeout 60s;
                proxy_read_timeout 60s;
                client_max_body_size 1m;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Port $server_port;
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_buffering on;

                proxy_pass http://harbor-harbor-harbor-ingress-core.harbor.domain-harbor-harbor-portal-80;


        }
# 省略...

可以看到,上面的 client_max_body_size的值为1m,这也就意味着上传文件的大小不能超过1M。

我们肯定不能直接修改这里的配置,因为nginx ingress一重启就又会变回1M。

这时候反过来查看harbor ingress的配置。

[root@master kubelet]# kubectl get ingress -n harbor
NAME                    HOSTS                                     ADDRESS   PORTS     AGE
harbor-harbor-ingress   core.harbor.domain,notary.harbor.domain             80, 443   4h1m
[root@master kubelet]# kubectl edit ingress harbor-harbor-ingress -n harbor

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    ingress.kubernetes.io/proxy-body-size: "0"
    ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: "0"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
  creationTimestamp: "2019-11-01T07:32:14Z"
  generation: 1
# 省略...

发现这里有一坨参数,也就是 metadata.annotations下面的部分,添加一行参数:

nginx.org/client-max-body-size: 500m

保存退出,这里的配置会自动同步到nginx ingress那边。

注,这里有个坑,出现这个错误,你去官网或者百度或者谷歌,几乎所有的资料都显示让你修改 proxy-body-size,但是实际上修改这个参数并没有一点效果。

注,还有另外一种方式是修改nginx ingress的ConfigMap中添加一行参数 client-max-body-size:500m

[root@master kubelet]# kubectl get configmap -n nginx-ingress
NAME           DATA   AGE
nginx-config   1      2d2h
[root@master kubelet]# kubectl edit configmap nginx-config -n nginx-ingress

# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
  server-names-hash-bucket-size: "1024"
  # client-max-body-size: 500m
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"server-names-hash-bucket-size":"1024"},"kind":"ConfigMap","metadata":{"annotations":{},"name":"nginx-config","namespace":"nginx-ingress"}}
  creationTimestamp: "2019-10-30T08:48:50Z"
  name: nginx-config
  namespace: nginx-ingress
  resourceVersion: "2986"
  selfLink: /api/v1/namespaces/nginx-ingress/configmaps/nginx-config
  uid: 38f98f6a-2107-4a42-9b82-58003606d371

注,如果遇到超时的问题,同样是修改Ingress的参数。

再次执行maven构建/推送命令,哎哟我操,终于成功了。

登录到harbor查看

打开项目test,发现下面多了个镜像,可以点进去看看,有一个标签(版本号),正是我们刚才提交的时间。

总结

本章的内容比较多,主要是坑有点多。

(1)maven中配置dockerfile插件;

(2)本地虚拟机中需要配置hosts;

(3)本地虚拟机中需要存放harbor仓库的证书;

(4)Ingress需要修改nginx上传文件body大小的限制。

坑其多也,踩之爽也。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 彤哥读源码 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 前提
  • 创建springboot应用
  • 编写Dockerfile文件
  • 集成时间插件
  • 集成dockerfile插件
  • 构建并推送到远程仓库
  • 无限踩坑过程
    • cannot conn to localhost:2375
      • lookup core.harbor.domain on 10.0.2.3:53: no such host
        • x509: certificate signed by unknown authority
          • denied: requested access to the resource is denied
            • 413 Request Entity Too Large
            • 登录到harbor查看
            • 总结
            相关产品与服务
            容器服务
            腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档