目录
一、k8s 核心概念
二、k8s 的优势
三、k8s 架构组件
控制平面组件
节点组件
四、k8s + docker 运行前后端分离项目的例子
1. 准备前端项目
2. 准备后端项目
3. 创建 k8s 部署配置文件
4. 部署应用到 k8s 集群
在当今云计算和容器化技术飞速发展的时代,Kubernetes(简称 k8s)已成为容器编排领域的事实标准。无论是互联网巨头、传统企业还是初创公司,都在广泛采用 k8s 来管理和部署容器化应用。本文将带你深入了解 k8s 的核心概念、优势以及架构组件,并通过一个具体的实例,展示如何使用 k8s + docker 运行前后端分离项目。
一、k8s 核心概念
要理解 k8s,首先需要掌握其几个核心概念,这些概念是 k8s 架构和功能的基础。
- Pod:Pod 是 k8s 中最小的部署单元,它可以包含一个或多个容器,这些容器共享网络命名空间和存储卷。也就是说,在同一个 Pod 内的容器可以通过localhost进行通信,并且可以访问相同的存储资源。Pod 的生命周期是短暂的,当 Pod 发生故障或需要更新时,k8s 会销毁旧的 Pod 并创建新的 Pod。
- Service:由于 Pod 的 IP 地址是动态变化的,这给应用之间的通信带来了困难。Service 就是为了解决这个问题而存在的,它为一组具有相同功能的 Pod 提供了一个固定的访问入口和负载均衡能力。Service 通过标签选择器与 Pod 关联,当 Pod 发生变化时,Service 会自动更新其关联的 Pod 列表。
- Deployment:Deployment 用于定义 Pod 的期望状态,它可以管理 Pod 的创建、更新和回滚等操作。通过 Deployment,我们可以指定 Pod 的副本数量、容器镜像版本等信息,k8s 会根据这些信息自动维持 Pod 的期望状态。当需要更新应用时,只需要修改 Deployment 中的容器镜像版本,k8s 就会逐步替换旧的 Pod,实现无缝更新。
- Namespace:Namespace 用于在 k8s 集群中创建多个虚拟集群,实现资源的隔离和管理。不同 Namespace 中的资源名称可以相同,这有助于在多租户环境中或不同项目之间进行资源隔离和权限控制。例如,我们可以为开发环境、测试环境和生产环境分别创建不同的 Namespace。
- ConfigMap 和 Secret:ConfigMap 用于存储应用的配置信息,如环境变量、配置文件等,它可以与 Pod 挂载,使应用能够方便地获取配置信息。Secret 与 ConfigMap 类似,但它用于存储敏感信息,如密码、密钥等,k8s 会对 Secret 进行加密处理,确保敏感信息的安全性。
二、k8s 的优势
k8s 之所以能够在容器编排领域占据主导地位,是因为它具有诸多显著的优势。
- 自动化运维:k8s 可以实现容器的自动部署、自动扩缩容、自动故障恢复等功能,大大减少了人工干预的工作量。例如,当某个 Pod 发生故障时,k8s 会自动检测到并创建一个新的 Pod 来替代它;当应用的负载增加时,k8s 可以根据预设的规则自动增加 Pod 的副本数量,以提高应用的处理能力。
- 弹性伸缩:k8s 支持根据 CPU 利用率、内存使用率等指标对 Pod 的副本数量进行自动扩缩容,也可以通过手动操作进行调整。这使得应用能够根据实际的业务需求灵活地调整资源配置,提高资源的利用率,降低运营成本。
- 服务发现与负载均衡:k8s 的 Service 组件提供了内置的服务发现和负载均衡功能,使得应用之间可以方便地进行通信。Service 会自动将请求分发到后端的多个 Pod 上,实现负载均衡,提高应用的可用性和稳定性。
- 滚动更新与回滚:通过 Deployment,k8s 可以实现应用的滚动更新,即在不中断服务的情况下逐步替换旧的 Pod。如果在更新过程中发现问题,可以快速回滚到之前的版本,降低了更新风险。
- 自愈能力:k8s 会持续监控 Pod 和节点的健康状态,当发现 Pod 或节点出现故障时,会自动采取相应的措施进行修复。例如,将故障 Pod 重新调度到健康的节点上,确保应用的持续运行。
三、k8s 架构组件
k8s 集群采用了主从架构,主要由控制平面(Control Plane)和节点(Node)两部分组成。
控制平面组件
控制平面负责整个集群的管理和决策,它包括以下几个核心组件:
- kube-apiserver:kube-apiserver 是 k8s 集群的前端接口,所有的操作都需要通过它来进行。它提供了 RESTful API,用于接收和处理用户的请求,同时也是其他组件之间通信的枢纽。
- etcd:etcd 是一个分布式键值存储系统,用于存储 k8s 集群的所有状态信息,如 Pod 的配置、Service 的定义等。etcd 具有高可用、一致性强等特点,是 k8s 集群的 “大脑”。
- kube-scheduler:kube-scheduler 负责 Pod 的调度工作,它会根据 Pod 的资源需求、节点的资源状况、亲和性和反亲和性规则等因素,为 Pod 选择最合适的节点进行部署。
- kube-controller-manager:kube-controller-manager 包含了多个控制器进程,如节点控制器、副本控制器、Deployment 控制器等。这些控制器负责监控集群的状态,并根据期望状态对集群进行调整,以确保集群的状态与期望状态一致。
- cloud-controller-manager:cloud-controller-manager 仅在使用云服务提供商的情况下才需要,它用于与云服务提供商的 API 进行交互,实现与云服务相关的功能,如节点的创建和删除、负载均衡器的管理等。
节点组件
节点是 k8s 集群中用于运行 Pod 的工作机器,它可以是物理机或虚拟机。节点上运行着以下组件:
- kubelet:kubelet 运行在每个节点上,它负责确保 Pod 中的容器按照 Pod 规范(PodSpec)正常运行。它会与 kube-apiserver 进行通信,接收并执行来自控制平面的指令,如创建、启动、停止 Pod 等。
- kube-proxy:kube-proxy 运行在每个节点上,它负责实现 Service 的功能,包括服务发现和负载均衡。它会维护节点上的网络规则,将请求转发到相应的 Pod 上。
- 容器运行时:容器运行时是用于运行容器的软件,如 Docker、containerd 等。k8s 通过容器运行时接口(CRI)与容器运行时进行交互,实现对容器的管理。
四、k8s + docker 运行前后端分离项目的例子
下面我们通过一个具体的例子,展示如何使用 k8s + docker 运行一个前后端分离的项目。假设我们有一个前端项目(基于 React)和一个后端项目(基于 Node.js),我们将分别为它们创建 Docker 镜像,然后使用 k8s 进行部署。
1. 准备前端项目
首先,我们需要为前端项目创建 Dockerfile。假设前端项目的目录结构如下:
frontend/
├── package.json
├── src/
└── public/
创建 Dockerfile:
# 构建阶段
FROM node:16-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build# 运行阶段
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
其中,nginx.conf 用于配置 nginx 的反向代理,将 API 请求转发到后端服务:
server {listen 80;root /usr/share/nginx/html;index index.html;location / {try_files $uri $uri/ /index.html;}location /api/ {proxy_pass http://backend-service:3000/api/;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}
}
构建前端镜像并推送到镜像仓库:
docker build -t frontend:v1 .
docker tag frontend:v1 your-registry/frontend:v1
docker push your-registry/frontend:v1
2. 准备后端项目
后端项目使用 Node.js,目录结构如下:
backend/
├── package.json
└── app.js
app.js 的内容如下:
const express = require('express');
const app = express();
const port = 3000;app.get('/api/data', (req, res) => {res.json({ message: 'Hello from backend!' });
});app.listen(port, () => {console.log(`Backend server running on port ${port}`);
});
创建 Dockerfile:
FROM node:16-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
构建后端镜像并推送到镜像仓库:
docker build -t backend:v1 .
docker tag backend:v1 your-registry/backend:v1
docker push your-registry/backend:v1
3. 创建 k8s 部署配置文件
创建前端 Deployment 和 Service 的配置文件(frontend-deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:name: frontend-deploymentnamespace: demo
spec:replicas: 2selector:matchLabels:app: frontendtemplate:metadata:labels:app: frontendspec:containers:- name: frontendimage: your-registry/frontend:v1ports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: frontend-servicenamespace: demo
spec:selector:app: frontendports:- port: 80targetPort: 80type: ClusterIP
创建后端 Deployment 和 Service 的配置文件(backend-deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:name: backend-deploymentnamespace: demo
spec:replicas: 2selector:matchLabels:app: backendtemplate:metadata:labels:app: backendspec:containers:- name: backendimage: your-registry/backend:v1ports:- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:name: backend-servicenamespace: demo
spec:selector:app: backendports:- port: 3000targetPort: 3000type: ClusterIP
创建 Ingress 配置文件(ingress.yaml),用于将外部流量导入到集群内部:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:name: demo-ingressnamespace: demo
spec:rules:- host: demo.example.comhttp:paths:- path: /pathType: Prefixbackend:service:name: frontend-serviceport:number: 80
4. 部署应用到 k8s 集群
首先,创建 Namespace:
kubectl create namespace demo
然后,部署前端和后端应用:
kubectl apply -f frontend-deployment.yaml
kubectl apply -f backend-deployment.yaml
最后,部署 Ingress:
kubectl apply -f ingress.yaml
部署完成后,可以通过以下命令查看部署情况:
kubectl get pods -n demo
kubectl get services -n demo
kubectl get ingress -n demo
此时,我们可以通过demo.example.com访问前端应用,前端应用会通过后端 Service 访问后端 API,实现前后端分离项目的运行。
通过以上例子,我们可以看到,使用 k8s + docker 运行前后端分离项目可以实现应用的自动化部署、弹性伸缩和高可用等特性,大大提高了应用的管理效率和可靠性。随着云计算技术的不断发展,k8s 的应用场景将会越来越广泛,掌握 k8s 已成为运维和开发人员的必备技能。希望本文能够帮助你更好地了解 k8s,并在实际项目中灵活运用。