第一部分:配置 docker

1.1、配置Nginx,转发 nexus 上传包的请求
sudo tee /etc/nginx/conf.d/k8s.conf <<-‘EOF’

HTTPS 服务器块

server {
listen 443 ssl;
server_name sls.registry.k8s;

# SSL 证书配置
ssl_certificate /home/projectname/server/mydomain.crt;
ssl_certificate_key /home/projectname/server/mydomain.key;

# 反向代理设置
location / {
    proxy_pass http://192.168.1.205:8082;
    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-Proto $scheme;
}

}
EOF

nginx -s reload

1.2、配置Nexus 调整上传附件的大小,确保能上传镜像
http {

// 新增下面这一行
client_max_body_size 2000M;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
// 修改这一行的值
keepalive_timeout 100;
types_hash_max_size 2048;

include /etc/nginx/mime.types;
default_type application/octet-stream;


ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;


access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;


gzip on;



include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;

}

1.3、配置docker 让docker 能访问nexus
1.3.1、nginx + nexus + docker 服务器
sudo tee /etc/docker/daemon.json <<-‘EOF’
{
“insecure-registries”: [ “sls.registry.k8s:443”,“192.168.1.205:8082”],
“registry-mirrors”: [ “https://sls.registry.k8s”,“http://192.168.1.205:8082”,“https://7e9g5tmw.mirror.aliyuncs.com”,“https://registry.docker-cn.com”],
“exec-opts”: [“native.cgroupdriver=systemd”]
}

EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

1.3.2、k8s 服务器:
sudo tee /etc/docker/daemon.json <<-‘EOF’
{
“insecure-registries”:[“sls.registry.k8s:5000”,“192.168.1.205:8082”],
“registry-mirrors”: [“https://sls.registry.k8s:5000”,“http://192.168.1.205:8082”,“https://7e9g5tmw.mirror.aliyuncs.com”]
}
EOF
sudo systemctl daemon-reload

第二部分: 安装NFS

2.1、安装NFS 服务器:
搭建一个 NFS(Network File System)服务器通常需要在 Linux 系统上进行操作。下面是一个基本的步骤指南:

步骤 1: 安装 NFS 服务器软件

  1. 使用包管理器安装 NFS 服务器软件。具体命令取决于你使用的 Linux 发行版。以 Ubuntu 为例,可以使用以下命令:

    sudo apt update
    sudo apt install nfs-kernel-server
    

步骤 2: 配置 NFS 服务器

  1. 编辑 NFS 服务器的配置文件。在 Ubuntu 上,配置文件位于 /etc/exports

    sudo nano /etc/exports
    
  2. 在配置文件中添加要共享的目录及其权限。例如,如果要共享 /srv/nfs_share 目录,可以添加类似以下内容:

    
    

/srv/nfs_share *(rw,sync,no_subtree_check)


- `/srv/nfs_share`: 要共享的目录路径。
- `*`: 允许所有客户端访问。
- `rw`: 可读写权限。
- `sync`: 同步写入。
- `no_subtree_check`: 不检查子目录。

3. 保存并关闭文件。

4. 更新 NFS 服务器配置:

sudo exportfs -a


### 步骤 3: 启动 NFS 服务器

1. 启动 NFS 服务器:

sudo systemctl start nfs-server


2. 如果需要,设置 NFS 服务器在系统启动时自动启动:

sudo systemctl enable nfs-server


### 步骤 4: 配置防火墙

1. 如果有防火墙启用,确保允许 NFS 流量通过。NFS 使用 UDP 和 TCP 端口 2049。

### 步骤 5: 配置客户端

1. 在客户端系统上安装 NFS 客户端软件。同样地,命令取决于你的 Linux 发行版。

2. 挂载 NFS 共享到客户端:

sudo mount <NFS服务器的IP或主机名>:<共享的目录> <本地挂载点>


例如:

sudo mount 192.168.1.205:/srv/nfs_share/projectname /mnt/nfs


### 注意事项:

- 确保网络中的所有主机能够解析 NFS 服务器的主机名或 IP 地址。
- 请根据实际需求调整配置,例如添加访问控制、更改权限等。
- 对于生产环境,确保数据的安全性和完整性。
- 测试 NFS 服务器和客户端之间的连接和数据访问,以确保一切正常运行。



以上是基本的 NFS 服务器搭建指南,具体步骤可能会因操作系统版本、网络环境等因素而略有不同。


2.2、在k8s集群上安装NFS 工具:

要在 Kubernetes 中挂载 NFS,你首先需要在你的 Kubernetes 集群所在的节点上安装 NFS 客户端。NFS 客户端软件通常在大多数 Linux 发行版的默认软件仓库中都可以找到。以下是在常见的几个 Linux 发行版上安装 NFS 客户端的方法:

1. **在 Ubuntu 上安装 NFS 客户端:**

sudo apt update
sudo apt install nfs-common


2. **在 CentOS/RHEL 上安装 NFS 客户端:**

sudo yum install nfs-utils


安装完成后,你就可以在 Kubernetes 节点上使用 `mount` 命令手动挂载 NFS 共享,以确保 NFS 客户端已经正确安装并且可以正常工作。例如:

sudo mount -t nfs <NFS服务器IP地址或域名>:/path/to/nfs/share /local/mount/point


这里的 `/local/mount/point` 是你希望将 NFS 共享挂载到的本地目录。

安装 NFS 客户端后,你可以按照之前提供的 Kubernetes 配置示例,在 Pod 中使用 Volume 来挂载 NFS 共享。确保在配置中正确设置了 NFS 服务器的地址和共享路径,并且在 Kubernetes 节点上已经可以通过 NFS 客户端正常访问该共享路径。

请注意,你需要确保在 Kubernetes 集群中的每个节点上都安装了 NFS 客户端,以便能够在所有节点上挂载 NFS 共享。

2.3、应用到POD:
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-app-projectname-keycloak-pv

配置标签供pvc选择

labels:
pv: local-app-projectname-keycloak-pv
spec:
capacity:
storage: 30Gi
accessModes: # 访问模式

  • ReadWriteMany # 读写权限,可以被多个节点挂载
    persistentVolumeReclaimPolicy: Retain

存储类型,与底层真正存储对应(nfs只是一个代表,这里还可以配置cifs、clusterfs或者其他存储类型)

nfs:
path: /srv/nfs_share/projectname
server: 192.168.1.205


apiVersion: v1
kind: PersistentVolumeClaim
metadata:

pvc的名字,提供给pod用于绑定

name: local-app-projectname-keycloak-pvc
namespace: local-app
spec:
accessModes:
- ReadWriteMany
resources: # 请求的空间
requests:
storage: 30Gi
selector: # 标签选择器绑定对应的PV
matchLabels:
pv: local-app-projectname-keycloak-pv


2.4、keycloak 配置分布式缓存:

<?xml version="1.0" encoding="UTF-8"?>
<jgroups>
    <!-- 定义一个名为"prod"的自定义JGroups堆栈 -->
    <stack name="prod">
        <!-- 使用TCP协议 -->
        <TCP bind_port="7800" port_range="30" recv_buf_size="20000000" send_buf_size="640000"/>
        <!-- RED插件 -->
        <RED/>
        <!-- MPING插件 -->
        <!-- 多播地址,默认为239.2.4.6 -->
        <!-- 多播端口,默认为43366 -->
        <!-- 发现运行次数,默认为3 -->
        <!-- IP数据包生存时间,默认为2 -->
        <MPING break_on_coord_rsp="true"
        mcast_addr="${jgroups.mping.mcast_addr:239.2.4.6}"
        mcast_port="${jgroups.mping.mcast_port:43366}"
        num_discovery_runs="3"
        ip_ttl="${jgroups.udp.ip_ttl:2}"/>
        <!-- MERGE3插件 -->
        <MERGE3 />
        <!-- FD_SOCK2插件 -->
        <FD_SOCK2 />
        <!-- FD_ALL3插件 -->
        <FD_ALL3 timeout="3000" interval="1000" timeout_check_interval="1000" />
        <!-- VERIFY_SUSPECT2插件 -->
        <VERIFY_SUSPECT2 timeout="1000" />
        <!-- pbcast.NAKACK2插件 -->
        <pbcast.NAKACK2 use_mcast_xmit="false" xmit_interval="200" xmit_table_num_rows="50"
                        xmit_table_msgs_per_row="1024" xmit_table_max_compaction_time="30000" />
        <!-- UNICAST3插件 -->
        <UNICAST3 conn_close_timeout="5000" xmit_interval="200" xmit_table_num_rows="50"
                  xmit_table_msgs_per_row="1024" xmit_table_max_compaction_time="30000" />
        <!-- pbcast.STABLE插件 -->
        <pbcast.STABLE desired_avg_gossip="2000" max_bytes="1M" />
        <!-- pbcast.GMS插件 -->
        <pbcast.GMS print_local_addr="false" join_timeout="${jgroups.join_timeout:2000}" />
        <!-- UFC插件 -->
        <UFC max_credits="4m" min_threshold="0.40" />
        <!-- MFC插件 -->
        <MFC max_credits="4m" min_threshold="0.40" />
        <!-- FRAG4插件 -->
        <FRAG4 />
    </stack>
</jgroups>

<cache-container name="keycloak">
    <transport cluster="my-cluster"/>
    <local-cache name="default">
        <transaction transaction-manager-lookup="org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup"/>
    </local-cache>
    <local-cache name="realms">
        <encoding>
            <key media-type="application/x-java-object"/>
            <value media-type="application/x-java-object"/>
        </encoding>
        <memory max-count="10000"/>
    </local-cache>
    <local-cache name="users">
        <encoding>
            <key media-type="application/x-java-object"/>
            <value media-type="application/x-java-object"/>
        </encoding>
        <memory max-count="10000"/>
    </local-cache>
    <distributed-cache name="sessions" owners="2"  mode="SYNC" statistics="true">
        <expiration lifespan="-1"/>
        <persistence>
            <file-store path="/projectname/sessions" preload="true"/>
        </persistence>
    </distributed-cache>
    <distributed-cache name="authenticationSessions"  mode="SYNC" owners="2"  statistics="true">
        <expiration lifespan="-1"/>
        <persistence>
            <file-store path="/projectname/authenticationSessions" preload="true"/>
        </persistence>
    </distributed-cache>
    <distributed-cache name="offlineSessions" owners="2"  mode="SYNC" statistics="true">
        <expiration lifespan="-1"/>
        <persistence>
            <file-store path="/projectname/offlineSessions" preload="true"/>
        </persistence>


    </distributed-cache>
    <distributed-cache name="clientSessions" owners="2"  mode="SYNC" statistics="true">
        <expiration lifespan="-1"/>
        <persistence>
            <file-store path="/projectname/clientSessions" preload="true"/>
        </persistence>

    </distributed-cache>
    <distributed-cache name="offlineClientSessions" owners="2"  mode="SYNC" statistics="true">
        <expiration lifespan="-1"/>
        <persistence>
            <file-store path="/projectname/offlineClientSessions" preload="true"/>
        </persistence>
    </distributed-cache>
    <distributed-cache name="loginFailures" owners="2"  mode="SYNC" statistics="true">
        <expiration lifespan="-1"/>
        <persistence>
            <file-store path="/projectname/loginFailures" preload="true"/>
        </persistence>

    </distributed-cache>
    <local-cache name="authorization"  statistics="true">
        <encoding>
            <key media-type="application/x-java-object"/>
            <value media-type="application/x-java-object"/>
        </encoding>
        <memory max-count="10000"/>
    </local-cache>
    <distributed-cache name="work"   owners="2"  mode="SYNC" statistics="true">
        <expiration lifespan="-1"/>
        <persistence>
            <file-store path="/projectname/work" preload="true"/>
        </persistence>
    </distributed-cache>
    <local-cache name="keys">
        <encoding>
            <key media-type="application/x-java-object"/>
            <value media-type="application/x-java-object"/>
        </encoding>
        <expiration max-idle="3600000"/>
    </local-cache>
    <distributed-cache name="actionTokens" owners="2"  mode="SYNC" statistics="true">
        <encoding>
            <key media-type="application/x-java-object"/>
            <value media-type="application/x-java-object"/>
        </encoding>
        <persistence>
            <file-store path="/projectname/actionTokens" preload="true"/>
        </persistence>

    </distributed-cache>
</cache-container>

3、配置 jenkins

def pom
def version = “0.1.4”;
def verDateStr = “20240401”;

pipeline {
agent any

stages {

   stage('Checkout') {
        steps {
            // 检出Keycloak代码
			 git credentialsId: 'MyCredentialsId', url: 'http://192.168.1.205:9980/projectname/porsso1903.git', branch: 'load_test'			
			
        }
    }
	
   
    stage('Build') {
        steps {
            sh 'cp -f conf/keycloak.conf quarkus/runtime/src/main/resources/META-INF/keycloak.conf'
            sh 'cp -rf conf/api.properties services/src/main/resources/api.properties'
            // 构建Keycloak			 
            sh 'mvn clean install -DskipTests'  
        }
    }
    
    stage('Docker Build & Push image to Nexus'){
		steps {
			script {
			    
			    version = params.version
			    
				echo "--------------Docker Build & Push image to Nexus-----------"+ version;
			//	pom = readMavenPom file: "./pom.xml" 
          
			  //  version = "${pom.properties.deployversion}"
			    
			    echo "docker阶段获取到的版本号:${version}"
				
				withCredentials([usernamePassword(credentialsId: 'Nexus', passwordVariable: 'password', usernameVariable: 'user')]) {
				    sh "docker -v"
				    sh "id jenkins"
			    	sh "docker build --build-arg JAR_VERSION=0.0.0.1.0 -f dockerfile2 -t sls.registry.k8s/projectname:${version} ." 
			 		sh "docker login sls.registry.k8s -u $user -p admin*****"
			 		sh "docker push sls.registry.k8s/projectname:${version}"
					sh "docker rmi sls.registry.k8s/projectname:${version}"
					echo "镜像删除成功"
				}
				
				echo "--------------------输出pom version:${version}---------------------"
			}
		}
	}
	
	stage('Deploy to k8s'){
		steps {
			script{
			    if(version == null){
		            version = input id: 'Version-Input', message: '版本号为空,请输入要部署的版本号,如:1.0.0', ok: 'yes', parameters: [string(description: '拉取镜像的版本号', name: 'input-version')], submitter: 'projectname'
		        
		            echo "input已经执行version=${version}"
		        }
		        version = params.version
			    verDateStr = "20240331";
				withCredentials([usernamePassword(credentialsId: 'k8s-master-login', passwordVariable: 'pass', usernameVariable: 'user')]) { 
                    sh "echo $user"
					sh "echo $pass"
                    def remote = [:]
                    remote.name = 'k8smaster'
                    remote.host = '192.168.1.222'
                    remote.user = "$user"
                    remote.password = "$pass"
                    remote.allowAnyHosts = true
					remote.pty=true
					
					try {
					    echo "k8s阶段获取到的版本号:${version}"

						sshCommand remote: remote, sudo: false, command: "sed -i -E 's/^( *image:.*projectname:)[0-9]+(\\.[0-9]+)*(.*)\$/\\1'${version}'\\3/' /home/projectname/keycloak/local-app-projectname-keycloak.yaml"
						sshCommand remote: remote, sudo: false, command: "sed -i -E 's/v[0-9]+\\.[0-9]+\\.[0-9]+_[0-9]+/v${verDateStr}/g'  /home/projectname/keycloak/local-app-projectname-keycloak.yaml"
						sshCommand remote: remote, sudo: true, command: "kubectl delete -f /home/projectname/keycloak/local-app-projectname-keycloak.yaml"
						sshCommand remote: remote, sudo: true, command: "kubectl apply -f /home/projectname/keycloak/local-app-projectname-keycloak.yaml"

						sshCommand remote: remote, sudo: true, command: "kubectl get pods --all-namespaces -o wide|grep app-projectname-keycloak"
						echo "try已执行!项目部署完成.."
					}catch (err){
						echo "我是catch发生错误了:${err}"
					}finally {
						echo "我是finally,yaml的镜像版本为${version}"
					}
                } 
			}
		}
	}
     
     
     
    
}

}

04-03 07:25