JumpServer 堡垒机 + K8s 高可用集群(十五)
JumperServer部署
开源 4A 运维安全审计平台,统一管控服务器、数据库、K8s 等资产,实现账号统一管理、登录权限控制、操作全程录像审计,满足等保合规,所有运维走堡垒机中转
系统Ubuntu 24.04 LTS
系统初始化
# 更新系统
apt update && apt upgrade -y
# 安装基础工具
apt install -y wget curl vim chrony iputils-ping openssh-server
# 时区同步
timedatectl set-timezone Asia/Shanghai
systemctl enable --now chronyd
# 关闭防火墙
ufw disable
systemctl stop ufw
systemctl disable ufw
# 关闭swap
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab
free -h
环境参数
# MySQL配置
MYSQL_IMAGE=mysql:8.0
MYSQL_CONTAINER=jms-mysql
MYSQL_ROOT_PASSWORD=Jump@123456
MYSQL_DATABASE=jumpserver
MYSQL_USER=jms
MYSQL_PASSWORD=Jump@654321
MYSQL_PORT=3306
# Redis配置
REDIS_IMAGE=redis:7-alpine
REDIS_CONTAINER=jms-redis
REDIS_PORT=6379
# JumpServer配置
JMS_IMAGE=jumpserver/jms-core:latest
JMS_CONTAINER=jms-core
JMS_PORT=80
# 宿主机持久化目录
mkdir -p /opt/jms/mysql /opt/jms/redis /opt/jms/core
安装 Docker 环境
安装 docker-ce、docker-compose
# 卸载旧版本
apt remove -y docker docker-engine docker.io containerd runc
# 安装依赖
apt install -y ca-certificates gnupg lsb-release
# 添加docker官方源
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装docker
apt update && apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 开机自启
systemctl enable --now docker
# 验证docker安装
docker -v
docker compose version
# 配置国内镜像加速
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://mirror.baidubce.com"]
}
EOF
systemctl restart docker
验证命令
docker run --rm hello-world
出现 Hello from Docker! 代表 Docker 环境正常。
安装 MySQL 服务
下载 MySQL 镜像查看默认配置
# 拉取镜像
docker pull ${MYSQL_IMAGE}
# 查看镜像内置环境变量默认配置
docker inspect ${MYSQL_IMAGE} | grep -i env
在宿主机准备 MySQL 配置文件
# 创建my.cnf配置
cat > /opt/jms/mysql/my.cnf <<EOF
[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
default-time_zone = '+8:00'
max_connections=1000
innodb_buffer_pool_size=1G
EOF
启动 MySQL 容器
docker run -d \
--name ${MYSQL_CONTAINER} \
--restart always \
-p ${MYSQL_PORT}:3306 \
-v /opt/jms/mysql:/var/lib/mysql \
-v /opt/jms/mysql/my.cnf:/etc/mysql/conf.d/my.cnf \
-e MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
-e MYSQL_DATABASE=${MYSQL_DATABASE} \
-e MYSQL_USER=${MYSQL_USER} \
-e MYSQL_PASSWORD=${MYSQL_PASSWORD} \
${MYSQL_IMAGE}
# 等待30秒初始化完成
sleep 30
验证 MySQL
# 进入容器连接数据库
docker exec -it ${MYSQL_CONTAINER} mysql -uroot -p${MYSQL_ROOT_PASSWORD}
# 执行验证SQL
show databases;
select user,host from mysql.user;
看到 jumpserver 库、jms 用户即正常,输入 exit 退出 MySQL
安装 Redis 服务
启动 Redis
# 拉取镜像
docker pull ${REDIS_IMAGE}
# 启动容器
docker run -d \
--name ${REDIS_CONTAINER} \
--restart always \
-p ${REDIS_PORT}:6379 \
-v /opt/jms/redis:/data \
${REDIS_IMAGE} redis-server --appendonly yes
验证 Redis 连接
# 进入redis客户端验证
docker exec -it ${REDIS_CONTAINER} redis-cli
# 测试写入读取
set test_key 123
get test_key
返回 123 代表 Redis 可用
部署 JumpServer
生成 key 和 token
# 生成SECRET_KEY
docker run --rm ${JMS_IMAGE} python -c "import secrets; print(secrets.token_urlsafe(48))"
# 生成BOOTSTRAP_TOKEN
docker run --rm ${JMS_IMAGE} python -c "import secrets; print(secrets.token_urlsafe(16))"
将两条输出字符串复制保存,下面启动容器需要填入。
SECRET_KEY="生成的48位密钥"
BOOTSTRAP_TOKEN="生成的16位token"
运行 JumpServer 核心容器
docker run -d \
--name ${JMS_CONTAINER} \
--restart always \
-p ${JMS_PORT}:80 \
-v /opt/jms/core:/opt/jumpserver/data \
-e SECRET_KEY=${SECRET_KEY} \
-e BOOTSTRAP_TOKEN=${BOOTSTRAP_TOKEN} \
-e DB_ENGINE=mysql \
-e DB_HOST=172.17.0.1 \
-e DB_PORT=${MYSQL_PORT} \
-e DB_USER=${MYSQL_USER} \
-e DB_PASSWORD=${MYSQL_PASSWORD} \
-e DB_NAME=${MYSQL_DATABASE} \
-e REDIS_HOST=172.17.0.1 \
-e REDIS_PORT=${REDIS_PORT} \
${JMS_IMAGE}
172.17.0.1 是 Docker 默认网桥宿主机网关,容器内可访问宿主机映射的 MySQL/Redis 端口。
验证是否成功
# 实时跟踪日志,等待初始化完成
docker logs -f ${JMS_CONTAINER}
出现 Application startup complete 代表服务启动完成
查看 MySQL 中生成相关表
# 登录MySQL查看jumpserver库数据表
docker exec -it ${MYSQL_CONTAINER} mysql -u${MYSQL_USER} -p${MYSQL_PASSWORD} ${MYSQL_DATABASE}
# 查看表
show tables;
查看端口
# 查看宿主机端口监听
ss -tlnp | grep -E "80|3306|6379"
# 查看容器端口映射
docker port ${JMS_CONTAINER}
docker port ${MYSQL_CONTAINER}
docker port ${REDIS_CONTAINER}
验证登录
- 浏览器访问:
http://服务器IP - 默认账号:
admin,默认密码:ChangeMe - 登录后强制修改初始密码,进入后台即部署完成。
案例:基于自定义网络利用 Docker 部署 JumpServer
创建自定义 docker 网络
docker network create jms-net
启动 MySQL 时加入自定义网络
docker run -d \
--name ${MYSQL_CONTAINER} \
--restart always \
--network jms-net \
-v /opt/jms/mysql:/var/lib/mysql \
-v /opt/jms/mysql/my.cnf:/etc/mysql/conf.d/my.cnf \
-e MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} \
-e MYSQL_DATABASE=${MYSQL_DATABASE} \
-e MYSQL_USER=${MYSQL_USER} \
-e MYSQL_PASSWORD=${MYSQL_PASSWORD} \
${MYSQL_IMAGE}
启动 Redis 加入自定义网络
docker run -d \
--name ${REDIS_CONTAINER} \
--restart always \
--network jms-net \
-v /opt/jms/redis:/data \
${REDIS_IMAGE} redis-server --appendonly yes
启动 JumpServer,使用容器名直接通信(DB_HOST=jms-mysql,无需 IP)
docker run -d \
--name ${JMS_CONTAINER} \
--restart always \
-p ${JMS_PORT}:80 \
--network jms-net \
-v /opt/jms/core:/opt/jumpserver/data \
-e SECRET_KEY=${SECRET_KEY} \
-e BOOTSTRAP_TOKEN=${BOOTSTRAP_TOKEN} \
-e DB_ENGINE=mysql \
-e DB_HOST=${MYSQL_CONTAINER} \
-e DB_PORT=3306 \
-e DB_USER=${MYSQL_USER} \
-e DB_PASSWORD=${MYSQL_PASSWORD} \
-e DB_NAME=${MYSQL_DATABASE} \
-e REDIS_HOST=${REDIS_CONTAINER} \
-e REDIS_PORT=6379 \
${JMS_IMAGE}
查看全部容器状态
docker ps -a
重置 admin 密码
docker exec -it ${JMS_CONTAINER} python manage.py reset_admin
jumperserver配置解析
核心密钥
SECRET_KEY:全局加密密钥,加密密码、录像、会话
BOOTSTRAP_TOKEN:组件通信令牌
2. MySQL 数据库
DB_ENGINE:数据库类型
DB_HOST:数据库地址
DB_PORT:数据库端口
DB_NAME:数据库库名
DB_USER:数据库账号
DB_PASSWORD:数据库密码
3. Redis 缓存
REDIS_HOST:Redis 地址
REDIS_PORT:Redis 端口
REDIS_PASSWORD:Redis 密码
4. Web 站点
HTTP_PORT:网页访问端口
SITE_URL:系统对外访问地址
5. 安全登录
SESSION_COOKIE_AGE:闲置会话超时时间
AUTH_MAX_FAILED:密码错误锁定次数
PASSWORD_MIN_LENGTH:密码最小长度
PASSWORD_COMPLEXITY:开启密码复杂度校验
ENABLE_CAPTCHA:登录验证码开关
6. 日志
LOG_LEVEL:日志输出级别(INFO/DEBUG)
7. 邮件告警
EMAIL_HOST:邮箱 SMTP 服务器
EMAIL_PORT:邮箱端口
EMAIL_HOST_USER:发件邮箱账号
EMAIL_HOST_PASSWORD:邮箱授权码
8. 终端连接
ASSET_CONNECT_TIMEOUT:资产连接超时
TERMINAL_MAX_SESSION:最大在线终端会话数
高可用K8S的部署
节点分配(3Master+3Worker 标准高可用)
| 主机 IP | 角色 | 主机名 |
|---|---|---|
| 192.168.9.101 | Master1 / 控制平面 | k8s-m01 |
| 192.168.9.102 | Master2 / 控制平面 | k8s-m02 |
| 192.168.9.103 | Master3 / 控制平面 | k8s-m03 |
| 192.168.9.104 | Worker 业务节点 | k8s-w01 |
| 192.168.9.105 | Worker 业务节点 | k8s-w02 |
| 192.168.9.106 | Worker 业务节点 | k8s-w03 |
控制面 VIP:192.168.9.100(Keepalived 漂移,统一 apiserver 入口)
所有节点统一初始化系统、关闭 swap、内核转发、安装 containerd+k8s 组件
Master 节点部署 HAProxy+Keepalived 实现 apiserver 高可用
网络插件:Calico Pod 网段 192.168.0.0/16
存储:外置共享存储 Ceph/NFS 提供 StorageClass
集群搭建
全节点统一初始化(101-106 全部执行)
apt update && apt upgrade -y
# 关闭防火墙
ufw disable
systemctl stop ufw && systemctl disable ufw
# 永久关闭swap
swapoff -a
sed -i '/swap/s/^/#/' /etc/fstab
# 内核网络转发
modprobe overlay
modprobe br_netfilter
cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
EOF
sysctl --system
# 设置主机名(分别执行对应主机名)
hostnamectl set-hostname k8s-m01
# 同步hosts解析
cat >> /etc/hosts <<EOF
192.168.9.101 k8s-m01
192.168.9.102 k8s-m02
192.168.9.103 k8s-m03
192.168.9.104 k8s-w01
192.168.9.105 k8s-w02
192.168.9.106 k8s-w03
EOF
全节点安装 containerd、kubeadm/kubelet/kubectl
统一版本安装,配置 cgroup 驱动为 systemd
# 安装依赖
apt install ca-certificates curl gnupg lsb-release -y
# docker源安装containerd
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list
apt update
apt install containerd.io -y
# 生成默认配置
containerd config default > /etc/containerd/config.toml
# 修改cgroup驱动为systemd
sed -i 's/SystemdCgroup \= false/SystemdCgroup \= true/g' /etc/containerd/config.toml
# 重启开机自启
systemctl restart containerd
systemctl enable containerd
安装 kubeadm/kubelet/kubectl 统一版本
# 添加k8s官方源
curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://packages.cloud.google.com/apt/doc/apt-key.gpg
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | tee /etc/apt/sources.list.d/kubernetes.list
apt update
# 固定v1.30.0版本
K8S_VER=1.30.0
apt install kubeadm=${K8S_VER}-00 kubelet=${K8S_VER}-00 kubectl=${K8S_VER}-00 -y
# 锁定版本防止自动更新
apt-mark hold kubeadm kubelet kubectl
# 验证版本
kubeadm version
kubectl version --client
三台 Master 部署 HAProxy+Keepalived(101/102/103 执行)
安装软件
apt install haproxy keepalived -y
systemctl enable haproxy keepalived
配置 HAProxy
vim /etc/haproxy/haproxy.cfg
global
log /dev/log local0
maxconn 10000
defaults
log global
mode tcp
retries 3
timeout connect 5s
timeout client 30s
timeout server 30s
frontend k8s-api
bind 192.168.9.100:6443
default_backend k8s-master
backend k8s-master
balance roundrobin
server m01 192.168.9.101:6443 check
server m02 192.168.9.102:6443 check
server m03 192.168.9.103:6443 check
Keepalived 配置(区分优先级,只改 state/priority)
m01(主节点 /etc/keepalived/keepalived.conf)
global_defs {
router_id LVS_M01
}
vrrp_instance VI_1 {
state MASTER
interface eth0 # 修改为本机网卡名
virtual_router_id 51
priority 100
advert_int 1
authentication {
auth_type PASS
auth_pass 123456
}
virtual_ipaddress {
192.168.9.100/24 dev eth0
}
}
m02
state BACKUP
priority 90
m03
state BACKUP
priority 80
重启生效
systemctl restart haproxy keepalived
# 验证VIP
ip a
Master1(101)初始化集群
kubeadm init --control-plane-endpoint 192.168.9.100:6443 \
--apiserver-advertise-address=192.168.9.101 \
--pod-network-cidr=192.168.0.0/16 \
--kubernetes-version=v1.30.0
执行完成输出两段命令,保存好:
- Master 扩容命令(带
--control-plane --certificate-key,给 m02/m03 用) - Worker 加入命令(给 w01/w02/w03 用)
拷贝管理员 kubeconfig
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
节点加入集群
Master2、Master3(102、103)执行 Master 加入命令
复制 kubeadm init 输出的 master join 命令
kubeadm join 192.168.9.100:6443 --token xxx \
--discovery-token-ca-cert-hash sha256:xxx \
--control-plane --certificate-key xxx
Worker 节点(104/105/106)执行 Worker 加入命令
kubeadm join 192.168.9.100:6443 --token xxx \
--discovery-token-ca-cert-hash sha256:xxx
token 过期重置:kubeadm token create --print-join-command
部署 Calico 网络插件(m01 执行)
kubectl apply -f https://docs.projectcalico.org/v3.28/manifests/calico.yaml
# 等待所有节点Ready
kubectl get nodes -w
# 全部状态Ready代表集群搭建完成
高可用通用部署规范(yaml 模板)
# 指定资源API版本,Deployment属于apps/v1分组
apiVersion: apps/v1
# 资源类型:控制器,用于无状态业务高可用部署
kind: Deployment
metadata:
# 控制器名称
name: demo-app
# 资源归属命名空间,隔离集群业务
namespace: prod
spec:
# Pod副本数量3个,多副本实现故障自动迁移
replicas: 3
selector:
# 匹配Pod标签,关联控制器与后端Pod
matchLabels:
app: demo
# Pod模板,定义Pod运行规范
template:
metadata:
# Pod自身标签,用于Service/Selector匹配
labels:
app: demo
spec:
# Pod亲和策略:反亲和,强制副本分散到不同节点
affinity:
podAntiAffinity:
# 硬策略,不满足条件则不调度Pod
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
# 匹配标签app=demo的Pod
- key: app
operator: In
values: [demo]
# 以宿主机节点为调度隔离维度
topologyKey: kubernetes.io/hostname
# 容器列表,一个Pod可包含多个容器
containers:
- name: demo # 容器名称
image: 业务镜像 # 业务镜像地址
# 从Secret批量注入环境变量,存放账号密码等敏感信息
envFrom:
- secretRef:
name: app-secret
# 容器资源配额,防止抢占集群资源引发雪崩
resources:
# 调度最低资源需求,调度器依据此分配节点
requests:
cpu: 100m
memory: 256Mi
# 资源硬上限,超出会被限流/杀死
limits:
cpu: 1000m
memory: 1Gi
# 存活探针:检测容器是否崩溃卡死,失败则重启Pod
livenessProbe:
httpGet:
path: /health # 健康检测接口路径
port: 80 # 容器服务端口
initialDelaySeconds: 5 # 容器启动5秒后开始检测
periodSeconds: 10 # 每10秒执行一次检测
# 就绪探针:检测业务是否可对外提供流量,失败则从Service剔除
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 3
periodSeconds: 5
# 存储挂载配置,将PVC绑定到容器内目录
volumeMounts:
- name: data # 存储卷名称,与下方volumes对应
mountPath: /data # 容器内持久化目录
# Pod挂载存储卷定义
volumes:
# 共享分布式存储卷,多Pod共用一份持久化数据
- name: data
persistentVolumeClaim:
claimName: app-pvc # 绑定提前创建的PVC资源
配套 Service+Ingress 负载均衡
# Service资源API版本
apiVersion: v1
# 资源类型:Service,实现Pod负载均衡与固定访问入口
kind: Service
metadata:
# Service名称
name: demo-svc
# 归属业务命名空间
namespace: prod
spec:
# 通过标签匹配后端Pod,流量转发至标签app=demo的Pod
selector:
app: demo
ports:
# 端口映射配置
- port: 80 # Service集群内部访问端口
targetPort: 80 # 后端Pod容器监听端口
# 服务类型:ClusterIP仅集群内部可访问,不暴露宿主机端口
type: ClusterIP
---
# Ingress网络资源API版本
apiVersion: networking.k8s.io/v1
# 资源类型:Ingress,提供集群外部域名访问入口
kind: Ingress
metadata:
name: demo-ing
namespace: prod
spec:
# 指定Ingress控制器,使用nginx-ingress组件处理流量
ingressClassName: nginx
# 域名路由规则列表
rules:
- host: demo.test.com # 外部访问域名
http:
paths:
# 路径匹配规则
- path: / # 匹配所有根路径请求
pathType: Prefix # 前缀匹配,/xxx全部命中
backend:
# 流量转发后端Service
service:
name: demo-svc # 关联上方创建的Service名称
port:
number: 80 # Service暴露端口
k8s资源作用
Deployment 无状态业务控制器,多副本、滚动更新、故障自动重建,实现高可用。
Service 给 Pod 固定访问入口,内置负载均衡,屏蔽 Pod IP 变化。
Ingress 域名反向代理,统一外部流量入口,支持域名 / 路径路由。
Secret 存放密码、密钥等敏感配置,明文不写入 YAML。
ConfigMap 普通配置文件、环境变量,非敏感参数。
PVC/PV 持久化存储,容器销毁数据不丢失,高可用集群用共享存储。
Namespace 资源隔离,区分不同业务环境。
Pod 最小运行单元,容器载体。
StatefulSet 有状态服务(MySQL/Redis),稳定网络标识、有序持久存储。
DaemonSet 每个节点运行一个 Pod,日志采集、监控代理专用。
yaml的字段含义
通用公共字段
apiVersion:资源所属 API 版本
kind:资源类型(Deployment/Service/Ingress)
metadata:元数据
name:资源名称
namespace:命名空间,资源隔离
labels:标签,用于 Service 筛选 Pod
spec:资源核心配置段
Deployment 字段
replicas:Pod 副本数量
selector.matchLabels:匹配 Pod 标签,关联控制器与 Pod
template:Pod 模板
spec.affinity:Pod 调度亲和 / 反亲和策略
containers:容器列表
image:业务镜像地址
envFrom:从 Secret/ConfigMap 读取环境变量
resources:容器 CPU、内存配额限制
livenessProbe:存活探针,卡死自动重启 Pod
readinessProbe:就绪探针,未就绪不接入流量
volumeMounts:PVC 挂载到容器内路径
volumes:定义持久化存储卷
persistentVolumeClaim:绑定 PVC 存储资源
Service 字段
selector:通过标签匹配后端 Pod
port:Service 集群访问端口
targetPort:Pod 容器监听端口
type:服务访问模式(ClusterIP 仅集群内访问)
Ingress 字段
ingressClassName:指定 nginx-ingress 控制器
rules.host:对外访问域名
path:请求匹配路径
pathType:匹配规则(Prefix 前缀匹配)
backend.service:流量转发目标 Service
更多推荐



所有评论(0)