百度360必应搜狗淘宝本站头条
当前位置:网站首页 > IT技术 > 正文

Docker是什么?K8s是什么?如何从0到1实现Docker与K8s全流程部署

wptr33 2025-01-09 16:35 28 浏览

云原生时代,作为技术人员,如果不了解 Docker 和 Kubernetes(K8s),那绝对是技术栈上的一个短板。那么,什么是 Docker?什么又是 Kubernetes?它们之间存在怎样的关系? 这篇文章,我将通过理论加代码实战的方式,详细地剖析他们。

1. 原理部分

1.1 Docker

Docker是一个容器化平台,它允许开发者将应用及其依赖项打包到一个称为容器的标准化单元中,以便可以在不同环境中快速、可靠地运行这些应用。它的本质是利用操作系统的CgroupsNamespace机制创建出来的隔离环境。

Docker核心概念包括以下几个:

1.1.1 Docker核心概念

1. 镜像:Docker(Image)镜像是一个轻量级、独立、可执行的软件包,其中包含运行某个应用程序所需的所有内容,包括代码、运行时、库、环境变量和配置文件。镜像是不可变的,基于镜像可以创建容器。

2. 容器:容器(Container)是镜像的运行实例,它是一个轻量级、独立的环境,可以在任何支持 Docker的机器上运行。容器与主机系统共享操作系统内核,但在进程空间上是隔离的。

3. Dockerfile:Dockerfile是一个文本文件,包含构建 Docker镜像的所有命令,可以通过 Dockerfile来自动化镜像的创建过程。

4. Docker Hub:Docker Hub是一个云端的 Docker镜像存储库,用户可以在上面发布和获取镜像,它提供了一个平台来共享和管理镜像。

5. 容器编排:Docker Compose是一种定义和运行多容器 Docker应用程序的工具,通过一个docker-compose.yml文件,用户可以定义一个应用包含的所有服务,并使用简单的命令启动或停止它们。

Docker容器可以描述成以下全景图(图片来自极客张磊):

1.1.2 Docker的优点

Docker的优点可以用一句话总结:一次打包,到处部署。这个和 JVM一次编译,到处运行的设计有着异曲同工之妙,所以说,计算机领域很多思维是相通的!

下图对比了使用与不使用 Docker的场景:

  • 不使用 Docker:每次将应用部署新主机时,都需要重新安装一遍应用需要的环境,因为操作系统多,运营商可能也不同,安装环境是一件痛苦的事情。
  • 使用 Docker:制作 Docker镜像时,已经包含应用及其所需的环境,因此可以到任何运营商提供的操作系统上运行。

1.2 Kubernetes

Kubernetes(K8s) 一词源自希腊,意为“舵手”或“掌舵者”,用于指导和管理船只的航行。它是一个容器编排平台,负责自动化容器的部署、扩展(水平扩展)、负载均衡、以及故障恢复等工作。

Kubernetes的核心概念包括以下几个:

1.2.1 Kubernetes核心概念

1. 节点:节点(Node)是 Kubernetes集群中的一台物理机或虚拟机,负责运行应用程序的工作负载。每个节点运行一个Kubelet(用于管理节点上的容器)和一个容器运行时(例如Docker)。

2. Pod:Pod是 Kubernetes中最小的可部署单元,通常包含一个或多个容器。Pod中的容器共享网络和存储,可以协同工作。

3. 控制器:控制器(Controller)负责管理和维护集群中的Pod和相关的服务。常见的控制器有 ReplicaSet(确保指定数量的Pod副本在运行)、Deployment(管理无状态应用)和 StatefulSet(管理有状态应用)。

4. 服务:服务(Service)是一个抽象的方式,用于定义一组Pod的逻辑集合以及访问这些 Pod的策略。Kubernetes中的服务提供了负载均衡和服务发现功能。

5. 命名空间:命名空间(Namespace)用于在同一个 Kubernetes集群中将资源进行逻辑上的隔离。它允许多个团队或项目共享一个集群而不会相互影响。

6. 配置管理:配置管理包含 ConfigMap 和 Secret。ConfigMap 用于存储非机密的数据,类似配置文件。Secret用于存储机密数据,如密码、OAuth令牌和SSH密钥。

7. Ingress:Ingress是一个 API对象,管理外部访问到集群中服务的 HTTP和 HTTPS路由。它提供负载均衡、SSL终止和基于名称的虚拟托管等功能。

8. Deployment:Deployment是一个用于管理无状态应用程序的核心组件。它提供了一种声明式的方法来管理 Pod和 ReplicaSet,从而实现应用程序的部署、升级和扩缩。

Kubernetes可以描述成以下全景图(图片来自极客张磊):

1.2.2 Kubernetes 的工作流程

Kubernetes 的整体工作流程可以总结成下面 6个步骤:

  1. 用户定义和提交文件:用户通过 kubectl提交描述文件,例如 Deployment 和 Service 定义,这些文件描述了应用副本数量、负责选择负载均衡的标签、资源需求等信息。
  2. API Server 接受请求:API Server处理用户的对象创建请求,这些请求会被记录在 etcd 中。
  3. 调度器决定 Pod 的位置:Scheduler根据集群的整体资源使用情况、节点健康状况、Pod 的资源要求等调度策略,将 Pod安排到集群中的某个 Node上。
  4. Kubelet 处理并运行Pod:在选定的 Node上,Kubelet调用 Container Runtime(例如 Docker 或 Container)启动容器,并根据请求的规格拉取镜像、分配资源、启动应用。
  5. Kube Proxy 实现服务访问:集群中的 Kube Proxy负责为每个 Pod生成虚拟 IP,通过这些 IP,集群内外部的访问可以通过 Kubernetes Services 来访问这些 Pod,进行负载均衡。
  6. 状态保持和自动修复:Kubernetes的控制器会持续监控 Pod和节点的状态,并在检测到某些 Pod不可用或节点失效时,自动重启或调度新的 Pod到健康的节点上。

整个流程如下图:

1.3 两者关系

Docker提供容器化机制,用于封装和打包应用,并利用 CI/CD管道将容器镜像推送至中央容器注册中心(如 Docker Hub 或 Harbor),而 Kubernetes是一个强大的容器编排平台,负责调度、扩展和管理 Docker容器化应用,保证系统高可用、故障自动恢复。

从宏观上看,两者关系可以通过下图来形象的表达:

好了,理论部分讲解完后,我们正式进入代码实战部分,俗话说:说起来容易做起来难,对于 Kubernetes集群还真有点难度,来,上干货!!!

2. 代码实战

2.1 目的

开发一个简单的 Java Web应用,并将其 Docker容器化部署到 Kubernetes集群中,然后在浏览器访问,展示:Hello world, This is my docker running in Kubernetes!。

实战部分基于: Apple M1 Pro电脑

2.2 步骤

整体流程核心步骤有下面 4个:

  1. 安装环境
  2. 创建 Web应用
  3. 应用 Docker 容器化
  4. 部署到 Kubernetes 集群
  5. 浏览器验证

2.2.1 安装环境

首先,需要确保我们安装了以下环境:JDK(Java Development Kit), Gradle(Maven),Docker, Kubernetes,下面是我安装的版本:

JDK 版本:

Gradle版本:

Docker 版本: 直接使用 Mac brew安装:

brew install --cask docker

Kubernetes 版本:

直接使用 Mac brew安装:

brew install kubectl

注意:Gradle 和 Maven 是项目管理工具,只要安装一个就OK,自己熟悉哪个就安装哪个。

2.2.2 创建Java Web应用

1. 创建Gradle(Maven)项目

创建一个 Springboot 项目,整个目录结构如下:

在src/main/cloud/com/yuanjava/docker目录下创建一个新的 Java类,如HelloController.java:

package com.yuanjava.docker;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @author 猿java
 */
@RestController
public class HelloController {
   @GetMapping("/test")
   public String test() {
      return "Hello world, This is my docker running in Kubernetes!";
   }
}

2. Gradle(Maven)打包项目:

Gradle打包指令如下:

gradle build

这里在 build/libs 目录下就就会看到打包后的 jar包:

2.2.3 容器化 Java Web应用

1. 编写Dockerfile:

在项目根目录下创建一个Dockerfile:

FROM openjdk:17-jdk-slim
COPY build/libs/yuanjava-1.0.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]

2. 构建Docker镜像:

在当前目录,运行以下命令就可以构建 Docker镜像,-t的作用是给这个镜像加一个Tag,也就是起一个好听的名字。

docker build -t yuanjava:1.0 .

运行完上面的指令之后,就可以在 Docker镜像库看到刚才打的镜像了,可以使用docker images指令查看镜像:

docker images

也可以通过 Docker的可视化工具查看镜像:

3. 运行Docker容器

我们可以通过下面的命令来启动 Docker容器:

docker run -p 9999:9999 yuanjava:1.0

然后,在浏览器中访问http://localhost:9999/test来测试 Docker是否启动完成。访问结果如下图:

4. 推送 Docker镜像到远程仓库

这一步是为了下面将 Docker镜像部署到 Kubernetes集群做准备,推送命令如下:

docker push yuanjava:1.0

推送完之后,远程仓库就多了一个镜像,如下图所示:

注意:如果没有 Docker账号,需要先创建账号。

2.2.4 部署到Kubernetes集群

1. 启动 Kubernetes集群

通常来说,我们会使用minikube命令来启动和管理 Kubernetes 集群,安装和启动命令如下:

# 安装 minikube
curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
chmod +x minikube
sudo mv minikube /usr/local/bin/

# 启动 Kubernetes集群
minikube start

2. 编写Kubernetes Deployment配置

创建一个deployment.yaml文件,内容如下:

apiVersion: apps/v1 # 定义了 Kubernetes API 的版本
kind: Deployment    # 声明这个 Kubernetes 资源的类型
metadata:
 name: yuanjava     # 包含资源的元数据,Kubernetes 通过 metadata 字段中的各类信息来跟踪和管理资源
spec:
 replicas: 2       # Pod的副本数量,即 Deployment将运行 2个相同的 Pod
 selector:
   matchLabels:
     app: yuanjava # 告诉 Deployment 如何找到它管理的 Pod
 template:
   metadata:
     labels:
       app: yuanjava # 定义 Pod 的模板
   spec:
     containers:
     - name: yuanjava
       image: yuanjava/yuanjava:1.0 #定义容器使用的镜像,Kubernetes 会从容器镜像仓库中拉取它
       ports:
       - containerPort: 9999     # 指定容器内部监听的应用端口

3. 编写Kubernetes Service配置

创建一个service.yaml文件,内容如下:

apiVersion: v1
kind: Service # 用于描述和管理向外部或者内部暴露应用的网络访问方式
metadata:
  name: yuanjava # 包含资源的元数据信息
spec:
  type: LoadBalancer # 定义了服务的类型,LoadBalancer 类型会将服务暴露给外部网络
  ports:
  - port: 80  # 这是对外暴露的端口,表示外部客户端访问服务时使用的端口号
    targetPort: 9999 # 这是集群内部目标 Pod 上运行的容器所监听的端口
  selector:
    app: yuanjava

4. 部署到Kubernetes

我们可以使用kubectl命令应用配置,命令说明如下:

kubectl apply -f deployment.yaml:根据 deployment.yaml 文件中的定义,创建或更新 Kubernetes中相应的 Deployment。 kubectl apply -f service.yaml:根据 service.yaml 文件中的内容,Kubernetes会创建一个 Service,并将其与运行 Deployment 中的 Pod关联起来。

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

5. 验证部署

使用以下命令检查 Pods和 Service状态:

kubectl get pods
kubectl get services

如下图,2个 Pod都处于 Running 状态:

2.2.5 浏览器验证

最后,我们可以在浏览器中访问,验证应用是否成功部署到 Kubernetes 集群,访问地址是:http://EXTERNAL-IP/hello ,如下图:

因为,我是本地部署,所以EXTERNAL-IP地址为<pending>,即未分配,但是可以通过minikube service yuanjava查看 IP地址,如下图所示:

最后,打开地址http://192.168.49.2:63213/test, 见证奇迹的时刻到了:

因为是本地环境,所以链接最终会跳转到http://127.0.0.1:63213/test 。

到此,我们就成功地手动将 Docker镜像部署到 Kubernetes集群,并且通过 URL能够访问,过程很艰辛,结果还是比较美好。

但是,如果要部署大量的机器,这样手动操作肯定是不行,因此,我们需要结组一些 CI/CD工具(如 GitHub Actions、GitLab CI/CD 或 Jenkins)实现自动化 Docker镜像构建和 Kubernetes 部署。

这里以 GitHub Actions为例,创建 .github/workflows/auto-deploy.yaml:

name: Auto Deploy Application to Kubernetes

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    # Step 1: 检出代码
    - name: Checkout code
      uses: actions/checkout@v3

    # Step 2: 登录 Docker Registry
    - name: Log in to Docker Hub
      run: echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin

    # Step 3: 构建并推送 Docker 镜像
    - name: Build and push Docker image
      run: |
        docker build -t ${{ secrets.DOCKER_USERNAME }}/yuanjava:latest .
        docker push ${{ secrets.DOCKER_USERNAME }}/yuanjava:latest

    # Step 4: 设置 kubectl
    - name: Set up kubectl
      uses: azure/setup-kubectl@v3
      with:
        version: 'latest'

    # Step 5: 配置 kubeconfig 文件
    - name: Configure kubeconfig
      run: |
        echo "${{ secrets.KUBECONFIG }}" > kubeconfig
        export KUBECONFIG=kubeconfig

    # Step 6: 部署到 Kubernetes
    - name: Apply Kubernetes manifests
      run: |
        kubectl apply -f deployment.yaml
        kubectl apply -f service.yaml

关键说明:

  • 配置里面的 DOCKER_USERNAME, DOCKER_PASSWORD, KUBECONFIG,需在项目的 Settings > Secrets 中配置。
  • 在触发阶段(push 到 main 分支)时,上述流水线将自动完成 Docker 构建、推送,并将应用部署到 Kubernetes。

3. 总结

本文,我们先从理论上分析了 Docker 和 Kubernetes的核心概念以及它们之间的关系。

接着,我们从代码实战的角度,带大家一步一步实操了如何编写一个简单的 Java Web应用,并将其 Docker容器化,最后部署到 Kubernetes集群中,然后在浏览器访问。在实操的期间,因为所有的环境都是本地环境临时搭建,所以遇到了很多的问题,但最终还是成功了。

通过这次实操,再次说明了做技术不能只停留在理论,实操很重要,实操期间我们可能遇到很多问题,但是,当我们通过各种方式去解决问题的时候,这个过程其实就是对技术更深入的学习和掌握。

个人建议:

Docker是云原生很重要相对简单的一个技术基础,强烈建议掌握并且一定要去实战。Kubernetes的难度系统会比 Docker大,它为大量容器提供调度、资源管理、弹性伸缩等功能,如果使用的机器数量比较少,Kubernetes其实很难用上,但是,如果可以,还是建议我们创造条件在实际生产环境中去使用和学习 Kubernetes。相信我,这种有压力的学习效果贼棒!

4. 参考资料

kubernetes官网

docker官网

学习交流

最后,把我的座右铭送给你:投资自己才是最大的财富。 如果你觉得本文章对你有帮助,点赞,收藏不迷路

公众号:我不是架构师,持续为你输出更多的硬核文章和面试经验。

相关推荐

MySQL进阶五之自动读写分离mysql-proxy

自动读写分离目前,大量现网用户的业务场景中存在读多写少、业务负载无法预测等情况,在有大量读请求的应用场景下,单个实例可能无法承受读取压力,甚至会对业务产生影响。为了实现读取能力的弹性扩展,分担数据库压...

Postgres vs MySQL_vs2022连接mysql数据库

...

3分钟短文 | Laravel SQL筛选两个日期之间的记录,怎么写?

引言今天说一个细分的需求,在模型中,或者使用laravel提供的EloquentORM功能,构造查询语句时,返回位于两个指定的日期之间的条目。应该怎么写?本文通过几个例子,为大家梳理一下。学习时...

一文由浅入深带你完全掌握MySQL的锁机制原理与应用

本文将跟大家聊聊InnoDB的锁。本文比较长,包括一条SQL是如何加锁的,一些加锁规则、如何分析和解决死锁问题等内容,建议耐心读完,肯定对大家有帮助的。为什么需要加锁呢?...

验证Mysql中联合索引的最左匹配原则

后端面试中一定是必问mysql的,在以往的面试中好几个面试官都反馈我Mysql基础不行,今天来着重复习一下自己的弱点知识。在Mysql调优中索引优化又是非常重要的方法,不管公司的大小只要后端项目中用到...

MySQL索引解析(联合索引/最左前缀/覆盖索引/索引下推)

目录1.索引基础...

你会看 MySQL 的执行计划(EXPLAIN)吗?

SQL执行太慢怎么办?我们通常会使用EXPLAIN命令来查看SQL的执行计划,然后根据执行计划找出问题所在并进行优化。用法简介...

MySQL 从入门到精通(四)之索引结构

索引概述索引(index),是帮助MySQL高效获取数据的数据结构(有序),在数据之外,数据库系统还维护者满足特定查询算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构...

mysql总结——面试中最常问到的知识点

mysql作为开源数据库中的榜一大哥,一直是面试官们考察的重中之重。今天,我们来总结一下mysql的知识点,供大家复习参照,看完这些知识点,再加上一些边角细节,基本上能够应付大多mysql相关面试了(...

mysql总结——面试中最常问到的知识点(2)

首先我们回顾一下上篇内容,主要复习了索引,事务,锁,以及SQL优化的工具。本篇文章接着写后面的内容。性能优化索引优化,SQL中索引的相关优化主要有以下几个方面:最好是全匹配。如果是联合索引的话,遵循最...

MySQL基础全知全解!超详细无废话!轻松上手~

本期内容提醒:全篇2300+字,篇幅较长,可搭配饭菜一同“食”用,全篇无废话(除了这句),干货满满,可收藏供后期反复观看。注:MySQL中语法不区分大小写,本篇中...

深入剖析 MySQL 中的锁机制原理_mysql 锁详解

在互联网软件开发领域,MySQL作为一款广泛应用的关系型数据库管理系统,其锁机制在保障数据一致性和实现并发控制方面扮演着举足轻重的角色。对于互联网软件开发人员而言,深入理解MySQL的锁机制原理...

Java 与 MySQL 性能优化:MySQL分区表设计与性能优化全解析

引言在数据库管理领域,随着数据量的不断增长,如何高效地管理和操作数据成为了一个关键问题。MySQL分区表作为一种有效的数据管理技术,能够将大型表划分为多个更小、更易管理的分区,从而提升数据库的性能和可...

MySQL基础篇:DQL数据查询操作_mysql 查

一、基础查询DQL基础查询语法SELECT字段列表FROM表名列表WHERE条件列表GROUPBY分组字段列表HAVING分组后条件列表ORDERBY排序字段列表LIMIT...

MySql:索引的基本使用_mysql索引的使用和原理

一、索引基础概念1.什么是索引?索引是数据库表的特殊数据结构(通常是B+树),用于...