504错误是啥 #
504 错误(Gateway Timeout)是一个 HTTP 状态码,表示网关或代理服务器超时。让我详细解释一下:
主要原因: #
服务器响应超时
- 上游服务器(如应用服务器)没有在预定时间内响应网关/代理服务器
- 可能是因为服务器负载过高或处理请求时间过长
网络问题
- 网关与上游服务器之间的网络连接存在问题
- 网络拥堵或延迟过高
常见场景: #
- 使用 Nginx 作为反向代理时,后端服务响应太慢
- 数据库查询操作耗时过长
- 服务器资源不足(CPU、内存等)
- 网络带宽不足
解决方案: #
服务器端
- 增加超时设置时间
- 优化后端代码性能
- 增加服务器资源
- 使用缓存减少处理时间
配置示例 如果使用 Nginx,可以调整超时设置:
http {
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
}
- 客户端
- 实现请求重试机制
- 添加适当的错误处理
- 考虑使用断路器模式
504 错误通常是临时性的,如果持续发生,建议检查服务器日志并进行相应优化。
常见的状态码 #
让我为你介绍最常见的 HTTP 状态码:
2XX - 成功响应 #
200 OK
- 最常见的成功状态码
- 请求成功且正常返回结果
201 Created
- 创建资源成功
- 通常在 POST 请求后返回
204 No Content
- 请求成功但无返回内容
- 常用于删除操作
3XX - 重定向 #
301 Moved Permanently
- 永久重定向
- 资源已永久移动到新位置
302 Found
- 临时重定向
- 资源临时移动到新位置
304 Not Modified
- 资源未修改
- 可使用缓存版本
4XX - 客户端错误 #
400 Bad Request
- 请求语法错误
- 服务器无法理解请求
401 Unauthorized
- 未授权
- 需要身份认证
403 Forbidden
- 禁止访问
- 服务器拒绝请求
404 Not Found
- 资源未找到
- 请求的资源不存在
429 Too Many Requests
- 请求过多
- 超出频率限制
5XX - 服务器错误 #
500 Internal Server Error
- 服务器内部错误
- 通常是代码异常
502 Bad Gateway
- 网关错误
- 上游服务器返回无效响应
503 Service Unavailable
- 服务不可用
- 服务器暂时无法处理请求
504 Gateway Timeout
- 网关超时
- 上游服务器响应超时
使用建议 #
- 在开发 API 时应合理使用状态码
- 确保错误响应包含有用的错误信息
- 在前端要对不同状态码进行适当处理
示例代码(前端处理):
fetch('api/data')
.then(response => {
switch(response.status) {
case 200:
return response.json();
case 401:
// 跳转到登录页
window.location.href = '/login';
break;
case 403:
throw new Error('没有权限访问');
case 404:
throw new Error('资源不存在');
default:
throw new Error('服务器错误');
}
})
.catch(error => {
console.error('请求失败:', error);
});
这些是最基本和常见的 HTTP 状态码,良好地使用它们可以帮助客户端更好地理解请求的处理结果。
k8s创建pod的过程 #
让我为你详细解释一下 Kubernetes 创建 Pod 的完整过程:
1. 提交请求阶段 #
用户提交请求
- 通过 kubectl 或 API 提交 Pod 创建请求
- API Server 接收请求并进行认证和授权
API Server 处理
- 验证 Pod 配置的合法性
- 将 Pod 信息持久化到 etcd
- 生成 Pod 的唯一标识符
2. 调度阶段 #
Scheduler 监听
- Scheduler 通过 Watch 机制发现新的未调度 Pod
调度算法执行
预选(Predicate)
- 筛选符合基本条件的节点
- 检查资源是否满足
- 检查节点亲和性/污点容忍
优选(Priority)
- 对预选节点进行打分
- 考虑负载均衡
- 选择最优节点
更新调度结果
- 将选中节点信息更新到 Pod 对象
- API Server 将更新后的 Pod 信息存储到 etcd
3. 创建阶段 #
Kubelet 监听
- 节点上的 Kubelet 发现被调度到本节点的 Pod
容器运行时准备
- 准备容器运行环境
- 下载容器镜像
- 配置容器网络
创建容器
- 按顺序创建 Init 容器
- 创建业务容器
- 配置健康检查
4. 运行阶段 #
状态监控
- Kubelet 持续监控 Pod 状态
- 执行配置的探针检查
- 更新 Pod 状态到 API Server
生命周期管理
- 处理容器重启
- 执行生命周期钩子
- 资源清理
示例 Pod 配置: #
apiVersion: v1
kind: Pod
metadata:
name: example-pod
labels:
app: example
spec:
containers:
- name: main-container
image: nginx:latest
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20
nodeSelector:
kubernetes.io/os: linux
可能的问题和解决方案: #
镜像拉取失败
- 检查镜像名称是否正确
- 确认镜像仓库访问权限
- 配置 imagePullSecrets
资源不足
- 调整资源请求和限制
- 增加节点资源
- 优化节点调度
网络问题
- 检查网络插件状态
- 验证网络策略配置
- 排查 DNS 解析问题
理解这个过程对于排查 Pod 创建问题和优化部署策略非常重要。每个阶段都可能出现问题,了解创建流程有助于快速定位和解决问题。
nginx 优化的措施
让我为你介绍 Nginx 的主要优化措施:
1. 基础配置优化 #
# nginx.conf 主要优化配置
worker_processes auto; # 根据 CPU 核心数自动设置
worker_rlimit_nofile 65535; # 增加工作进程文件描述符限制
events {
use epoll; # 使用 epoll 事件模型
worker_connections 65535; # 增加每个工作进程的最大连接数
multi_accept on; # 开启一次接受多个连接
}
http {
# 开启 gzip 压缩
gzip on;
gzip_comp_level 5;
gzip_min_length 1k;
gzip_types text/plain text/css application/javascript application/json;
# 缓存相关
open_file_cache max=1000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# 客户端优化
client_max_body_size 20m; # 上传文件大小限制
keepalive_timeout 65; # 保持连接超时时间
client_body_buffer_size 128k; # 请求体缓冲区大小
}
2. 静态文件优化 #
- 启用缓存控制
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d; # 设置缓存过期时间
add_header Cache-Control public;
access_log off; # 关闭访问日志
}
- 启用 sendfile
http {
sendfile on; # 启用零拷贝
tcp_nopush on; # 优化数据包传输
tcp_nodelay on; # 禁用 Nagle 算法
}
3. 负载均衡优化 #
upstream backend {
least_conn; # 最少连接数算法
server backend1.example.com max_fails=3 fail_timeout=30s;
server backend2.example.com max_fails=3 fail_timeout=30s;
keepalive 32; # 保持后端连接数
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_next_upstream error timeout http_500; # 故障转移
}
}
4. SSL 优化 #
http {
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
}
5. 安全优化 #
server {
# 隐藏版本号
server_tokens off;
# XSS 防护
add_header X-XSS-Protection "1; mode=block";
# 点击劫持防护
add_header X-Frame-Options "SAMEORIGIN";
# 限制请求频率
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
location /login/ {
limit_req zone=one burst=5;
}
}
6. 日志优化 #
http {
# 自定义日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 缓冲日志写入
access_log /var/log/nginx/access.log main buffer=32k flush=1m;
# 对特定资源关闭日志
location /static/ {
access_log off;
}
}
7. 监控指标 #
- 配置 stub_status 模块监控 Nginx 状态:
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
优化建议: #
定期监控
- 监控连接数
- 监控请求延迟
- 监控错误率
- 监控资源使用
性能测试
- 使用 ab、wrk 等工具进行压力测试
- 根据测试结果调整配置
定期维护
- 清理日志文件
- 更新 SSL 证书
- 检查配置是否最优
这些优化措施需要根据实际情况选择性使用,不是所有的优化都适用于所有场景。建议在测试环境验证后再应用到生产环境。
gitlab的runner 干嘛的 #
GitLab Runner 是 GitLab CI/CD 的执行器,主要负责运行 CI/CD 流水线中定义的作业(Jobs)。让我详细解释一下:
1. Runner 的主要功能 #
执行 CI/CD 作业
- 运行测试
- 构建应用
- 部署服务
- 自动化任务
支持多种执行方式
- Shell 执行器
- Docker 执行器
- Kubernetes 执行器
- 虚拟机执行器
2. Runner 类型 #
共享 Runner
- 所有项目可用
- 由 GitLab 管理员配置
- 适合通用构建任务
特定 Runner
- 专门为特定项目服务
- 由项目维护者配置
- 适合特殊需求的项目
3. 配置示例 #
以下是一个典型的 .gitlab-ci.yml
配置文件示例:
stages:
- build
- test
- deploy
build-job:
stage: build
script:
- echo "编译代码..."
- mvn package
artifacts:
paths:
- target/*.jar
test-job:
stage: test
script:
- echo "运行测试..."
- mvn test
deploy-job:
stage: deploy
script:
- echo "部署应用..."
- kubectl apply -f pod.yaml
only:
- master
4. Runner 在 Kubernetes 中的配置 #
如果使用 Kubernetes 执行器,需要配置类似这样的 Runner:
apiVersion: apps/v1
kind: Deployment
metadata:
name: gitlab-runner
namespace: gitlab
spec:
replicas: 1
selector:
matchLabels:
app: gitlab-runner
template:
metadata:
labels:
app: gitlab-runner
spec:
containers:
- name: gitlab-runner
image: gitlab/gitlab-runner:latest
args:
- run
volumeMounts:
- name: config
mountPath: /etc/gitlab-runner
- name: docker-sock
mountPath: /var/run/docker.sock
volumes:
- name: config
configMap:
name: gitlab-runner-config
- name: docker-sock
hostPath:
path: /var/run/docker.sock
5. Runner 注册配置 #
Runner 需要注册到 GitLab 才能使用,配置示例:
gitlab-runner register \
--non-interactive \
--url "https://gitlab.example.com/" \
--registration-token "PROJECT_REGISTRATION_TOKEN" \
--executor "docker" \
--docker-image alpine:latest \
--description "docker-runner" \
--tag-list "docker,aws" \
--run-untagged="true" \
--locked="false"
6. 常见使用场景 #
自动化测试
- 单元测试
- 集成测试
- 代码质量检查
自动化构建
- 编译代码
- 构建 Docker 镜像
- 生成制品
自动化部署
- 部署到测试环境
- 部署到生产环境
- 更新 K8s 配置
7. 最佳实践 #
资源管理
- 合理设置并发数
- 配置作业超时时间
- 清理构建缓存
安全考虑
- 使用安全的执行器
- 限制 Runner 权限
- 保护敏感信息
性能优化
- 使用缓存加速构建
- 选择合适的执行器
- 优化构建脚本
GitLab Runner 是 CI/CD 流程中的重要组件,合理配置和使用可以大大提高开发团队的效率。
jenkins常用插件 #
让我介绍一下 Jenkins 最常用和最实用的插件:
1. 基础功能插件 #
Credentials Plugin
- 凭证管理
- 存储密码、密钥、Token 等
- 支持多种凭证类型
Git Plugin
- Git 代码仓库集成
- 支持分支、标签管理
- 代码检出配置
Pipeline
- 流水线支持
- 支持 Jenkinsfile
- 可视化流水线编辑器
2. 构建相关插件 #
- Maven Integration
// Jenkinsfile 示例
pipeline {
agent any
tools {
maven 'Maven 3.8.1'
}
stages {
stage('Build') {
steps {
sh 'mvn clean package'
}
}
}
}
- Gradle Plugin
// Jenkinsfile 示例
pipeline {
agent any
stages {
stage('Build') {
steps {
gradle 'clean build'
}
}
}
}
3. 容器相关插件 #
- Docker Plugin
// Jenkinsfile 示例
pipeline {
agent {
docker {
image 'maven:3.8.1-jdk-8'
}
}
stages {
stage('Build') {
steps {
sh 'mvn package'
}
}
}
}
- Kubernetes Plugin
// Jenkinsfile 示例
pipeline {
agent {
kubernetes {
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- name: maven
image: maven:3.8.1-jdk-8
command:
- cat
tty: true
'''
}
}
stages {
stage('Build') {
steps {
container('maven') {
sh 'mvn package'
}
}
}
}
}
4. 代码质量插件 #
- SonarQube Scanner
// Jenkinsfile 示例
pipeline {
agent any
stages {
stage('SonarQube Analysis') {
steps {
withSonarQubeEnv('SonarQube') {
sh 'mvn sonar:sonar'
}
}
}
}
}
- Checkstyle
// Jenkinsfile 示例
pipeline {
agent any
stages {
stage('Code Analysis') {
steps {
sh 'mvn checkstyle:checkstyle'
}
post {
always {
recordIssues(tools: [checkStyle()])
}
}
}
}
}
5. 通知类插件 #
- Email Extension Plugin
// Jenkinsfile 示例
pipeline {
agent any
post {
failure {
emailext (
subject: "构建失败: ${env.JOB_NAME} [${env.BUILD_NUMBER}]",
body: """<p>构建失败:</p>
<p>查看: <a href='${env.BUILD_URL}'>${env.JOB_NAME} [${env.BUILD_NUMBER}]</a></p>""",
to: "team@example.com"
)
}
}
}
- 钉钉通知插件
// Jenkinsfile 示例
pipeline {
agent any
post {
always {
dingtalk (
robot: '钉钉机器人TOKEN',
type: 'MARKDOWN',
title: '构建通知',
text: [
"### 构建结果: ${currentBuild.result}",
"- 项目: ${env.JOB_NAME}",
"- 构建号: ${env.BUILD_NUMBER}",
"- 详情: [查看](${env.BUILD_URL})"
]
)
}
}
}
6. 其他实用插件 #
Timestamper
- 为控制台输出添加时间戳
- 方便调试和日志分析
AnsiColor
- 支持控制台彩色输出
- 提高日志可读性
Build Timeout
// Jenkinsfile 示例
pipeline {
agent any
options {
timeout(time: 1, unit: 'HOURS')
}
stages {
stage('Build') {
steps {
sh 'mvn package'
}
}
}
}
安装建议 #
按需安装
- 避免安装过多不必要的插件
- 定期清理未使用的插件
版本兼容
- 注意插件之间的版本兼容性
- 定期更新插件到最新稳定版
性能考虑
- 插件过多会影响 Jenkins 性能
- 建议只保留必要的插件
这些插件能够显著提升 Jenkins 的功能和使用体验,但建议根据实际需求选择安装。
声明式和脚本式的jenkins的写法举例 #
让我介绍几种 Jenkins 运行多个任务的方案:
1. 并行执行 (Parallel) #
pipeline {
agent any
stages {
stage('并行任务') {
parallel {
stage('任务A') {
steps {
sh 'mvn test -Dtest=TestA'
}
}
stage('任务B') {
steps {
sh 'mvn test -Dtest=TestB'
}
}
stage('任务C') {
steps {
sh 'docker build -t imageA .'
}
}
}
}
}
}
2. 矩阵构建 (Matrix) #
pipeline {
agent any
matrix {
axes {
axis {
name 'PLATFORM'
values 'linux', 'windows', 'mac'
}
axis {
name 'BROWSER'
values 'chrome', 'firefox', 'safari'
}
}
stages {
stage('测试') {
steps {
sh "run-tests.sh ${PLATFORM} ${BROWSER}"
}
}
}
}
}
3. 多分支流水线 #
pipeline {
agent any
stages {
stage('构建') {
when {
anyOf {
branch 'main'
branch 'develop'
branch 'feature/*'
}
}
steps {
sh 'mvn clean package'
}
}
stage('部署开发环境') {
when { branch 'develop' }
steps {
sh 'deploy-to-dev.sh'
}
}
stage('部署生产环境') {
when { branch 'main' }
steps {
sh 'deploy-to-prod.sh'
}
}
}
}
4. 上游/下游任务 (Upstream/Downstream) #
pipeline {
agent any
stages {
stage('触发下游任务') {
steps {
build job: 'downstream-job-1', wait: false
build job: 'downstream-job-2', wait: false
parallel (
"任务1": {
build job: 'parallel-job-1'
},
"任务2": {
build job: 'parallel-job-2'
}
)
}
}
}
post {
success {
build job: 'notification-job',
parameters: [string(name: 'STATUS', value: 'SUCCESS')]
}
}
}
5. 参数化构建矩阵 #
pipeline {
agent any
parameters {
choice(
name: 'ENVIRONMENT',
choices: ['dev', 'test', 'prod'],
description: '选择部署环境'
)
booleanParam(
name: 'RUN_TESTS',
defaultValue: true,
description: '是否运行测试'
)
}
stages {
stage('并行任务') {
parallel {
stage('部署') {
steps {
sh "deploy-to-${params.ENVIRONMENT}.sh"
}
}
stage('测试') {
when { expression { params.RUN_TESTS } }
steps {
sh 'run-tests.sh'
}
}
}
}
}
}
6. 资源分配和限制 #
pipeline {
agent none
stages {
stage('并行构建') {
parallel {
stage('Java构建') {
agent {
label 'java-builder'
}
steps {
sh 'mvn clean package'
}
}
stage('Node构建') {
agent {
label 'node-builder'
}
steps {
sh 'npm install && npm run build'
}
}
}
}
}
options {
parallelsAlwaysFailFast()
}
}
最佳实践建议: #
资源管理
- 合理设置并发数
- 注意资源使用限制
- 避免资源竞争
错误处理
- 设置超时限制
- 合理处理任务失败
- 配置重试机制
性能优化
- 合理使用并行执行
- 避免不必要的等待
- 优化构建顺序
监控和通知
- 配置构建状态通知
- 监控资源使用情况
- 记录构建历史
通过这些方式,你可以根据具体需求选择合适的多任务执行方案,提高构建效率和资源利用率。
怎么确保密码 这些不会明文写到流水线里面 #
在 Jenkins 中,有几个关于敏感信息输出的重要注意点:
1. 默认行为 #
- 凭据变量
- 通过
credentials()
绑定的变量默认是被 Jenkins 保护的 - 即使使用
echo $PASSWORD
也会显示为****
- 环境变量
- 普通环境变量不会自动被掩码
- 需要特别注意不要直接打印
2. 安全处理示例 #
pipeline {
agent any
environment {
// 这样定义的凭据会自动被保护
DB_CREDS = credentials('db-credentials')
// 普通环境变量需要注意保护
API_KEY = 'sensitive-value'
}
stages {
stage('安全示例') {
steps {
script {
// 错误示例 - 不要这样做
// sh "echo $API_KEY" // 会暴露敏感信息
// 正确示例
wrap([$class: 'MaskPasswordsBuildWrapper',
varPasswordPairs: [[var: 'API_KEY', password: env.API_KEY]]]) {
// 现在 API_KEY 会被自动掩码
sh 'curl -H "Authorization: Bearer $API_KEY" https://api.example.com'
}
}
// credentials() 绑定的变量会自动被保护
withCredentials([
usernamePassword(
credentialsId: 'my-credentials',
usernameVariable: 'USER',
passwordVariable: 'PASS'
)
]) {
// 即使echo,也会显示为 ****
sh 'echo $PASS'
}
}
}
}
}
3. 最佳实践 #
- 使用凭据插件
withCredentials([string(credentialsId: 'my-secret', variable: 'SECRET')]) {
// SECRET 变量会自动被掩码
sh './deploy.sh' // 在脚本中使用 $SECRET
}
- 使用掩码包装器
wrap([$class: 'MaskPasswordsBuildWrapper', varPasswordPairs: [
[var: 'PASSWORD', password: 'sensitive-value']
]]) {
// 所有输出中的 'sensitive-value' 都会被替换为 ****
sh 'your-command'
}
- 避免直接输出
// 不要这样做
sh "echo 'Using password: $PASSWORD'"
// 而是这样
sh '''
if [ -n "$PASSWORD" ]; then
echo "Password is configured"
else
echo "Password is missing"
fi
'''
- 日志处理
options {
// 设置构建日志保留策略
buildDiscarder(logRotator(numToKeepStr: '10'))
}
4. 安全检查清单 #
- 避免
- 直接 echo 敏感变量
- 在命令参数中显示密码
- 在构建日志中保留敏感信息
- 应该
- 使用凭据插件管理敏感信息
- 使用掩码包装器保护变量
- 定期审查构建日志
- 限制日志访问权限
- 配置建议
pipeline {
agent any
options {
// 禁用并发构建
disableConcurrentBuilds()
// 设置超时
timeout(time: 1, unit: 'HOURS')
}
environment {
// 使用凭据绑定
DEPLOY_KEY = credentials('deploy-key')
}
stages {
stage('部署') {
steps {
// 使用安全的方式处理敏感信息
withCredentials([
file(credentialsId: 'kubeconfig', variable: 'KUBECONFIG')
]) {
sh 'kubectl apply -f deployment.yaml'
}
}
}
}
}
通过这些措施,可以有效防止敏感信息在构建过程中被泄露。
说下你对容器和k8s的理解 #
让我分享下对容器和 Kubernetes 的理解:
1. 容器的本质 #
隔离性
- 使用 Linux 的 Namespace 技术实现资源隔离
- 每个容器有自己的进程空间、网络空间、挂载空间等
- 容器间互不影响
资源限制
- 使用 Linux 的 Cgroups 技术限制资源使用
- 可以限制 CPU、内存、IO 等资源
- 防止单个容器占用过多资源
轻量级
- 共享主机内核
- 秒级启动
- 资源利用率高
2. K8s 的核心功能 #
- 自动化管理
# Deployment 自动管理 Pod 的生命周期
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 3 # 自动维护3个副本
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
自愈能力
- 节点故障自动迁移
- 容器崩溃自动重启
- 健康检查和恢复
负载均衡
# Service 提供负载均衡
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 80
3. 架构设计理念 #
声明式 API
- 描述期望状态
- 系统自动调整实际状态
- 易于维护和自动化
控制器模式
- 每个控制器负责特定资源
- 持续监控和调整状态
- 松耦合设计
水平扩展
# HPA 自动扩缩容
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: nginx-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: nginx
minReplicas: 1
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
4. 实际应用场景 #
微服务架构
- 服务独立部署
- 快速迭代
- 弹性伸缩
DevOps 实践
- 持续集成/部署
- 自动化运维
- 环境一致性
高可用设计
# Pod 反亲和性确保高可用
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
spec:
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- webapp
topologyKey: "kubernetes.io/hostname"
5. 生产环境考虑 #
资源管理
- 合理设置请求和限制
- 资源预留和超卖
- 成本优化
安全性
# 网络策略隔离
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-allow
spec:
podSelector:
matchLabels:
app: api
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
- 可观测性
- 监控指标
- 日志收集
- 链路追踪
6. 最佳实践 #
容器设计
- 单一职责
- 无状态设计
- 合理的资源限制
- 健康检查
K8s 配置
- 使用命名空间隔离
- 实施资源配额
- RBAC 权限控制
- 备份和恢复策略
运维管理
- 监控告警
- 日志管理
- 灾备方案
- 升级策略
容器和 Kubernetes 的结合极大地改变了应用部署和运维的方式,提供了一个强大的平台来运行和管理现代应用。理解它们的核心概念和最佳实践对于构建可靠的生产系统至关重要。
我看到你有一个 pod.yaml 文件,让我基于这个实际的配置文件来进一步解释一些重要概念。
从你的 pod.yaml 文件中可以看到几个关键的最佳实践:
1. 资源管理 #
resources:
requests:
memory: "64Mi" # 保证最小内存
cpu: "250m" # 0.25 CPU
limits:
memory: "256Mi" # 内存上限
cpu: "500m" # 0.5 CPU
这里展示了合理的资源控制:
- requests: 保证 Pod 运行的最小资源
- limits: 限制资源使用的上限
- 设置合适的比例(limits/requests)避免资源浪费
2. 健康检查 #
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20
两种探针的使用:
- readinessProbe: 确定 Pod 是否准备好接收流量
- livenessProbe: 确定 Pod 是否需要重启
3. 配置管理 #
volumeMounts:
- name: config
mountPath: /app/config
volumes:
- name: config
configMap:
name: app-config
使用 ConfigMap 管理配置:
- 配置与代码分离
- 可以动态更新
- 便于环境管理
4. 节点选择 #
nodeSelector:
kubernetes.io/os: linux
通过标签选择合适的节点:
- 确保 Pod 调度到正确的节点
- 可以基于操作系统、硬件特性等选择
这些配置反映了在生产环境中运行容器的几个重要考虑点:
- 资源控制
- 可靠性保证
- 配置管理
- 调度策略
这是一个比较完善的 Pod 配置,体现了 K8s 的核心价值:自动化管理、高可用性和可维护性。
你用过go或者python写东西吗 有关运维的 devops的 #
是的,我经常使用 Python 和 Go 来编写运维和 DevOps 相关的工具。让我分享一些常见的场景和示例:
1. Python 自动化运维示例 #
- K8s 资源监控
from kubernetes import client, config
def monitor_pods():
# 加载 k8s 配置
config.load_kube_config()
v1 = client.CoreV1Api()
try:
# 获取所有 namespace 的 pods
pods = v1.list_pod_for_all_namespaces(watch=False)
for pod in pods.items:
print(f"Pod: {pod.metadata.name}")
print(f"Namespace: {pod.metadata.namespace}")
print(f"Status: {pod.status.phase}")
# 检查资源使用
if pod.status.container_statuses:
for container in pod.status.container_statuses:
print(f"Container: {container.name}")
print(f"Ready: {container.ready}")
print(f"Restart Count: {container.restart_count}")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
monitor_pods()
- 日志分析工具
import re
from datetime import datetime
import pandas as pd
def analyze_nginx_logs(log_file):
# 定义日志格式正则
pattern = r'(?P<ip>.*?) - - \[(?P<time>.*?)\] "(?P<request>.*?)" (?P<status>\d+) (?P<size>\d+)'
logs = []
with open(log_file, 'r') as f:
for line in f:
match = re.match(pattern, line)
if match:
data = match.groupdict()
data['time'] = datetime.strptime(data['time'], '%d/%b/%Y:%H:%M:%S %z')
logs.append(data)
# 转换为 DataFrame 分析
df = pd.DataFrame(logs)
return {
'total_requests': len(df),
'status_codes': df['status'].value_counts().to_dict(),
'top_ips': df['ip'].value_counts().head(10).to_dict()
}
2. Go 运维工具示例 #
- Docker 容器监控
package main
import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
)
func monitorContainers() {
ctx := context.Background()
cli, err := client.NewClientWithOpts(client.FromEnv)
if err != nil {
panic(err)
}
containers, err := cli.ContainerList(ctx, types.ContainerListOptions{})
if err != nil {
panic(err)
}
for _, container := range containers {
stats, err := cli.ContainerStats(ctx, container.ID, false)
if err != nil {
fmt.Printf("Error getting stats for %s: %v\n", container.ID, err)
continue
}
fmt.Printf("Container: %s\n", container.Names[0])
fmt.Printf("Status: %s\n", container.Status)
fmt.Printf("Stats: %v\n", stats)
}
}
- 自动化部署工具
package main
import (
"fmt"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
appsv1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func deployApplication(namespace, name string, image string) error {
// 加载 kubeconfig
config, err := clientcmd.BuildConfigFromFlags("", "~/.kube/config")
if err != nil {
return err
}
// 创建 clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return err
}
// 创建 deployment
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: appsv1.DeploymentSpec{
Replicas: int32Ptr(3),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": name,
},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"app": name,
},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: name,
Image: image,
},
},
},
},
},
}
// 执行部署
_, err = clientset.AppsV1().Deployments(namespace).Create(context.TODO(), deployment, metav1.CreateOptions{})
return err
}
3. 实用的 DevOps 脚本 #
- CI/CD 辅助工具
import requests
import json
import os
class GitlabCI:
def __init__(self, token, url):
self.token = token
self.url = url
self.headers = {'PRIVATE-TOKEN': token}
def trigger_pipeline(self, project_id, ref='main'):
endpoint = f"{self.url}/api/v4/projects/{project_id}/pipeline"
data = {'ref': ref}
response = requests.post(endpoint, headers=self.headers, data=data)
return response.json()
def get_pipeline_status(self, project_id, pipeline_id):
endpoint = f"{self.url}/api/v4/projects/{project_id}/pipelines/{pipeline_id}"
response = requests.get(endpoint, headers=self.headers)
return response.json()
- 资源清理工具
from kubernetes import client, config
from datetime import datetime, timedelta
def cleanup_old_pods(namespace, hours=24):
config.load_kube_config()
v1 = client.CoreV1Api()
try:
pods = v1.list_namespaced_pod(namespace)
now = datetime.now(timezone.utc)
for pod in pods.items:
if pod.status.phase in ['Failed', 'Succeeded']:
created_time = pod.metadata.creation_timestamp
age = now - created_time
if age > timedelta(hours=hours):
print(f"Deleting pod: {pod.metadata.name}")
v1.delete_namespaced_pod(
pod.metadata.name,
namespace,
body=client.V1DeleteOptions()
)
except Exception as e:
print(f"Error during cleanup: {e}")
这些工具都是基于实际运维需求开发的。主要特点:
自动化
- 减少人工操作
- 提高效率
- 降低错误率
监控告警
- 实时监控系统状态
- 及时发现问题
- 自动处理或通知
运维管理
- 资源清理
- 配置管理
- 日志分析
持续集成/部署
- 自动化构建
- 自动化测试
- 自动化部署
根据实际需求,这些工具可以进一步定制和扩展。
让我基于你的 pod.yaml 文件,写一个实用的 Python 脚本来监控和管理这个 Pod:
from kubernetes import client, config
import time
from datetime import datetime
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
class PodMonitor:
def __init__(self, namespace="default"):
# 加载 k8s 配置
config.load_kube_config()
self.v1 = client.CoreV1Api()
self.namespace = namespace
def monitor_pod_resources(self, pod_name):
"""监控 Pod 的资源使用情况"""
try:
pod = self.v1.read_namespaced_pod(pod_name, self.namespace)
# 检查资源限制和请求
for container in pod.spec.containers:
resources = container.resources
logger.info(f"Container: {container.name}")
logger.info(f"Resource Limits: {resources.limits}")
logger.info(f"Resource Requests: {resources.requests}")
# 检查 Pod 状态
logger.info(f"Pod Status: {pod.status.phase}")
# 检查就绪状态
if pod.status.container_statuses:
for container in pod.status.container_statuses:
logger.info(f"Container {container.name} Ready: {container.ready}")
logger.info(f"Restart Count: {container.restart_count}")
except Exception as e:
logger.error(f"Error monitoring pod {pod_name}: {e}")
def check_probes(self, pod_name):
"""检查 Pod 的健康检查状态"""
try:
pod = self.v1.read_namespaced_pod(pod_name, self.namespace)
for container in pod.spec.containers:
logger.info(f"Container: {container.name}")
if container.readiness_probe:
logger.info("Readiness Probe:")
logger.info(f"Initial Delay: {container.readiness_probe.initial_delay_seconds}s")
logger.info(f"Period: {container.readiness_probe.period_seconds}s")
if container.liveness_probe:
logger.info("Liveness Probe:")
logger.info(f"Initial Delay: {container.liveness_probe.initial_delay_seconds}s")
logger.info(f"Period: {container.liveness_probe.period_seconds}s")
except Exception as e:
logger.error(f"Error checking probes for pod {pod_name}: {e}")
def check_configmap_mounted(self, pod_name):
"""检查 ConfigMap 挂载状态"""
try:
pod = self.v1.read_namespaced_pod(pod_name, self.namespace)
for volume in pod.spec.volumes:
if volume.config_map:
logger.info(f"ConfigMap mounted: {volume.config_map.name}")
# 检查 ConfigMap 是否存在
try:
config_map = self.v1.read_namespaced_config_map(
volume.config_map.name,
self.namespace
)
logger.info("ConfigMap exists and is accessible")
except Exception as e:
logger.error(f"Error accessing ConfigMap: {e}")
except Exception as e:
logger.error(f"Error checking ConfigMap for pod {pod_name}: {e}")
def continuous_monitoring(self, pod_name, interval=60):
"""持续监控 Pod"""
while True:
logger.info(f"\n=== Monitoring Pod {pod_name} at {datetime.now()} ===")
self.monitor_pod_resources(pod_name)
self.check_probes(pod_name)
self.check_configmap_mounted(pod_name)
time.sleep(interval)
def main():
monitor = PodMonitor()
pod_name = "app-pod" # 你的 pod 名称
try:
monitor.continuous_monitoring(pod_name)
except KeyboardInterrupt:
logger.info("Monitoring stopped by user")
except Exception as e:
logger.error(f"Unexpected error: {e}")
if __name__ == "__main__":
main()
这个脚本提供了以下功能:
资源监控
- 检查 CPU 和内存使用
- 监控容器状态
- 跟踪重启次数
健康检查监控
- 监控 readinessProbe
- 监控 livenessProbe
- 检查探针配置
配置检查
- 验证 ConfigMap 挂载
- 检查 ConfigMap 可访问性
持续监控
- 定期检查 Pod 状态
- 输出详细日志
- 异常处理和报告
你可以根据需要调整监控间隔和添加其他监控指标。要使用这个脚本,需要先安装 kubernetes 客户端:
pip install kubernetes
这个工具可以帮助你更好地监控和管理你的 Pod。
我再基于你的 pod.yaml 写一个更实用的 Go 版本的监控工具,这个版本会更关注性能和并发处理:
package main
import (
"context"
"fmt"
"time"
"log"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
"path/filepath"
)
type PodMonitor struct {
clientset *kubernetes.Clientset
namespace string
}
func NewPodMonitor(namespace string) (*PodMonitor, error) {
// 获取 kubeconfig 路径
kubeconfig := filepath.Join(homedir.HomeDir(), ".kube", "config")
// 创建 config
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
return nil, fmt.Errorf("error building config: %v", err)
}
// 创建 clientset
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, fmt.Errorf("error creating clientset: %v", err)
}
return &PodMonitor{
clientset: clientset,
namespace: namespace,
}, nil
}
func (pm *PodMonitor) MonitorPod(ctx context.Context, podName string) {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
log.Println("Monitoring stopped")
return
case <-ticker.C:
pod, err := pm.clientset.CoreV1().Pods(pm.namespace).Get(
context.Background(),
podName,
metav1.GetOptions{},
)
if err != nil {
log.Printf("Error getting pod %s: %v\n", podName, err)
continue
}
// 检查 Pod 状态
log.Printf("Pod Status: %s\n", pod.Status.Phase)
// 检查容器状态
for _, container := range pod.Status.ContainerStatuses {
log.Printf("Container: %s\n", container.Name)
log.Printf(" Ready: %v\n", container.Ready)
log.Printf(" RestartCount: %d\n", container.RestartCount)
// 检查资源使用
if container.State.Running != nil {
log.Printf(" Running since: %v\n", container.State.Running.StartedAt)
}
}
// 检查资源配置
for _, container := range pod.Spec.Containers {
resources := container.Resources
log.Printf("Resource Limits - CPU: %s, Memory: %s\n",
resources.Limits.Cpu(),
resources.Limits.Memory(),
)
log.Printf("Resource Requests - CPU: %s, Memory: %s\n",
resources.Requests.Cpu(),
resources.Requests.Memory(),
)
}
}
}
}
func (pm *PodMonitor) CheckProbes(podName string) error {
pod, err := pm.clientset.CoreV1().Pods(pm.namespace).Get(
context.Background(),
podName,
metav1.GetOptions{},
)
if err != nil {
return fmt.Errorf("error getting pod: %v", err)
}
for _, container := range pod.Spec.Containers {
log.Printf("Container: %s\n", container.Name)
if container.ReadinessProbe != nil {
log.Printf("ReadinessProbe:\n")
log.Printf(" InitialDelay: %ds\n", container.ReadinessProbe.InitialDelaySeconds)
log.Printf(" Period: %ds\n", container.ReadinessProbe.PeriodSeconds)
}
if container.LivenessProbe != nil {
log.Printf("LivenessProbe:\n")
log.Printf(" InitialDelay: %ds\n", container.LivenessProbe.InitialDelaySeconds)
log.Printf(" Period: %ds\n", container.LivenessProbe.PeriodSeconds)
}
}
return nil
}
func main() {
monitor, err := NewPodMonitor("default")
if err != nil {
log.Fatalf("Error creating monitor: %v", err)
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// 启动监控
go monitor.MonitorPod(ctx, "app-pod")
// 检查探针配置
if err := monitor.CheckProbes("app-pod"); err != nil {
log.Printf("Error checking probes: %v\n", err)
}
// 保持程序运行
select {
case <-ctx.Done():
log.Println("Program terminated")
}
}
这个 Go 版本的监控工具具有以下特点:
性能更好
- 使用 Go 的并发特性
- 更低的资源消耗
- 更快的响应速度
更好的错误处理
- 使用 context 控制生命周期
- 详细的错误信息
- 优雅的退出机制
功能完整
- 监控 Pod 状态
- 检查资源使用
- 探针状态监控
要运行这个程序,需要先安装依赖:
go get k8s.io/client-go@latest
这个工具比 Python 版本的性能更好,特别是在需要长期运行或监控多个 Pod 的场景下。
减少docker镜像的体积大小 #
基于减少 Docker 镜像体积,我来举例说明几种常用的优化方法:
1. 多阶段构建 (Multi-stage Build) #
# 构建阶段
FROM maven:3.8.1-jdk-8 AS builder
WORKDIR /app
COPY pom.xml .
# 缓存依赖
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 运行阶段 - 使用更小的基础镜像
FROM openjdk:8-jre-alpine
WORKDIR /app
# 只复制构建产物
COPY --from=builder /app/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
2. 使用轻量级基础镜像 #
# 不推荐
FROM ubuntu:latest # ~70MB
# 推荐
FROM alpine:latest # ~5MB
3. 优化 RUN 指令和清理 #
FROM python:3.9-alpine
WORKDIR /app
COPY requirements.txt .
# 合并命令并清理缓存
RUN pip install --no-cache-dir -r requirements.txt && \
rm -rf /root/.cache/pip && \
rm -rf /var/cache/apk/*
COPY . .
4. 使用 .dockerignore #
# 排除不需要的文件
node_modules
*.log
.git
.env
*.md
tests
docs
*.pyc
__pycache__
.pytest_cache
5. 生产环境优化示例 #
# Node.js 应用优化示例
FROM node:alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 使用更轻量的镜像运行
FROM nginx:alpine
COPY --from=builder /app/build /usr/share/nginx/html
EXPOSE 80
6. 分离开发和生产依赖 #
# 开发环境
FROM node:alpine AS development
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
# 生产环境
FROM node:alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY --from=development /app/dist ./dist
CMD ["node", "dist/main"]
7. 最佳实践总结 #
选择合适的基础镜像
- 使用官方镜像
- 选择 alpine 版本
- 使用特定版本标签
优化构建过程
- 合并 RUN 指令
- 清理缓存文件
- 使用多阶段构建
文件处理
- 使用 .dockerignore
- 只复制必要文件
- 删除临时文件
依赖管理
- 只安装生产依赖
- 使用版本锁定
- 清理包管理器缓存
8. 实际示例(基于你的 pod.yaml) #
# 多阶段构建示例
FROM node:alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 生产镜像
FROM nginx:alpine
# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html
# 复制 nginx 配置
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 设置用户
USER nginx
# 资源使用限制(对应 pod.yaml 中的设置)
ENV NODE_OPTIONS="--max-old-space-size=256"
EXPOSE 80
# 健康检查
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -q --spider http://localhost/ || exit 1
这些优化可以显著减少镜像大小,提高部署效率。记住要根据实际应用需求选择适当的优化策略。
多阶段构建啥意思 #
多阶段构建(Multi-stage Build)是一种优化 Docker 镜像大小的技术。让我用具体例子解释:
1. 传统构建方式(单阶段) #
# 这种方式最终镜像会包含构建工具和中间文件,体积很大
FROM maven:3.8.1-jdk-8
WORKDIR /app
COPY . .
RUN mvn package
CMD ["java", "-jar", "target/app.jar"]
2. 多阶段构建方式 #
# 第一阶段:构建阶段
FROM maven:3.8.1-jdk-8 AS builder
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn package
# 第二阶段:运行阶段
FROM openjdk:8-jre-alpine
WORKDIR /app
# 只复制第一阶段构建的产物
COPY --from=builder /app/target/*.jar app.jar
CMD ["java", "-jar", "app.jar"]
主要优点:
- 最终镜像更小:只包含运行必需的文件
- 更安全:不包含构建工具和源代码
- 层更少:优化缓存和构建速度
3. 更复杂的多阶段构建示例 #
# 第一阶段:依赖安装
FROM node:alpine AS dependencies
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
# 第二阶段:构建
FROM node:alpine AS builder
WORKDIR /app
COPY --from=dependencies /app/node_modules ./node_modules
COPY . .
RUN npm run build
# 第三阶段:运行
FROM nginx:alpine
# 只复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html
# 配置文件
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
这个例子中:
- 第一阶段安装依赖
- 第二阶段进行构建
- 第三阶段只包含运行所需的文件
最终镜像只包含:
- nginx 运行环境
- 构建后的静态文件
- nginx 配置
不包含:
- node.js 环境
- npm 包
- 源代码
- 构建工具
这样可以大大减少最终镜像的大小,通常可以减少 60-90% 的体积。
好的,我看到你有一个 pod.yaml 文件。让我结合你的 pod.yaml 配置,写一个实际的多阶段构建的例子,这样可以确保构建出的镜像既小巧又符合你的资源限制要求:
# 第一阶段:依赖安装和构建
FROM node:alpine AS builder
WORKDIR /app
# 安装依赖
COPY package*.json ./
RUN npm ci --only=production
# 复制源代码并构建
COPY . .
RUN npm run build
# 第二阶段:运行环境
FROM nginx:alpine
WORKDIR /usr/share/nginx/html
# 从builder阶段复制构建产物
COPY --from=builder /app/dist .
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 设置非root用户运行
USER nginx
# 配置健康检查,对应 pod.yaml 中的探针配置
HEALTHCHECK --interval=10s --timeout=3s \
CMD wget -q --spider http://localhost/ || exit 1
# 资源使用优化,对应 pod.yaml 中的资源限制
ENV NODE_OPTIONS="--max-old-space-size=256"
EXPOSE 80
这个 Dockerfile:
- 构建阶段只包含必要的构建工具
- 运行阶段使用轻量级的 alpine 基础镜像
- 最终镜像符合 pod.yaml 中的资源限制和健康检查要求
这样构建出的镜像会更小,更适合在你的 K8s 环境中运行。
是的!我注意到你的 pod.yaml 配置得很规范,包含了资源限制、健康检查等重要配置。让我们可以进一步优化 Dockerfile,使其完全匹配你的 pod.yaml 配置:
# 第一阶段:构建
FROM node:alpine AS builder
WORKDIR /app
# 使用 .dockerignore 排除不必要文件
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 第二阶段:运行
FROM nginx:alpine
WORKDIR /usr/share/nginx/html
# 对应 pod.yaml 中的资源限制
# memory: "256Mi"
# cpu: "500m"
ENV NGINX_WORKER_PROCESSES="auto"
ENV NGINX_WORKER_CONNECTIONS="1024"
# 复制构建产物
COPY --from=builder /app/dist .
COPY nginx.conf /etc/nginx/conf.d/default.conf
# 对应 pod.yaml 中的健康检查配置
# readinessProbe 和 livenessProbe
HEALTHCHECK --interval=10s --timeout=3s \
CMD wget -q --spider http://localhost/ || exit 1
# 安全性配置
USER nginx
EXPOSE 80
这样构建出的镜像不仅体积小,而且完全符合你在 pod.yaml 中定义的运行要求。你觉得这样的优化方向对吗?