hello云胜

技术与生活

0%

redis4.x版本集群搭建(不使用ruby版本)

集群模式3主3从。

在三台机器上分别启动2个redis实例。步骤可参考以前的文章。

之前配置集群使用的是ruby方案。安装ruby比较麻烦,我不喜欢。其实是可以直接使用redis自己的指令完成的。虽然步骤多一点,(也不多,只要三步)。但是redis的原生方案更放心。

redis的5.x版本更方便了,只需要一个命令,见后续文章。

cluster meet

第一步将所有redis实例之间建立联系。

随便选择一个redis实例执行

1
2
3
4
5
6
7
8
9
10
11
# redis-cli -h 127.0.0.1 -p 6379 -a xxxxxx
127.0.0.1:6379> cluster meet 1x.xxx.8.10 6380
OK
127.0.0.1:6379> cluster meet 1x.xxx.8.11 6379
OK
127.0.0.1:6379> cluster meet 1x.xxx.8.11 6380
OK
127.0.0.1:6379> cluster meet 1x.xxx.8.12 6379
OK
127.0.0.1:6379> cluster meet 1x.xxx.8.12 6380
OK

查看一下状态

1
2
3
4
5
6
7
127.0.0.1:6379> cluster nodes
23c4a4663cac558243226819ced0ae9f7474d661 1x.xxx.8.10:6379@16379 myself,master - 0 1671593497000 3 connected
07813601b89542172c1eda310f4d175ebf4b145b 1x.xxx.8.11:6379@16379 master - 0 1671593498000 2 connected
a05e7b4314147e86c674dc7203ddce9be142f2e3 1x.xxx.8.12:6380@16380 master - 0 1671593497000 5 connected
0057e3eac5dca123de6a0febeaa55a4f589d5cfc 1x.xxx.8.10:6380@16380 master - 0 1671593497117 1 connected
f54487779ead35e41d878aa876ea456576f8da60 1x.xxx.8.11:6380@16380 master - 0 1671593499120 0 connected
a79a1d40bc9f6830f62bb98e2936209d24925593 1x.xxx.8.12:6379@16379 master - 0 1671593498119 4 connected

主从配置

现在6个实例全部加入集群,但是主从关系还没有分配。

分配主从的时候要注意,主节点和对应的从节点应该部署在不同的服务器上,以取得高可用性。

image-20221221134748957

分别登录3个备节点,执行replicate指令

1
2
3
4
5
6
# redis-cli -h 1x.xxx.8.10 -p 6380 -a xxxxxxx cluster replicate a79a1d40bc9f6830f62bb98e2936209d24925593
OK
# redis-cli -h 1x.xxx.8.11 -p 6380 -a xxxxxxx cluster replicate 23c4a4663cac558243226819ced0ae9f7474d661
OK
# redis-cli -h 1x.xxx.8.12 -p 6380 -a xxxxxxx cluster replicate 07813601b89542172c1eda310f4d175ebf4b145b
OK

查看节点状态

1
2
3
4
5
6
7
# redis-cli -h 1x.xxx.8.12 -p 6380 -a xxxxxx cluster nodes
a79a1d40bc9f6830f62bb98e2936209d24925593 1x.xxx.8.12:6379@16379 master - 0 1671601584000 4 connected
f54487779ead35e41d878aa876ea456576f8da60 1x.xxx.8.11:6380@16380 slave 23c4a4663cac558243226819ced0ae9f7474d661 0 1671601585000 3 connected
a05e7b4314147e86c674dc7203ddce9be142f2e3 1x.xxx.8.12:6380@16380 myself,slave 07813601b89542172c1eda310f4d175ebf4b145b 0 1671601584000 5 connected
0057e3eac5dca123de6a0febeaa55a4f589d5cfc 1x.xxx.8.10:6380@16380 slave a79a1d40bc9f6830f62bb98e2936209d24925593 0 1671601587266 4 connected
07813601b89542172c1eda310f4d175ebf4b145b 1x.xxx.8.11:6379@16379 master - 0 1671601586264 2 connected
23c4a4663cac558243226819ced0ae9f7474d661 1x.xxx.8.10:6379@16379 master - 0 1671601586000 3 connected

分配slot

redis集群共有16384个slot。我们平均分。序号是从0开始,到16383结束。必须全部分配,缺一个都不行。

分配slot只在master节点上执行。

1
2
3
4
5
6
# redis-cli -h 1x.xxx.8.10 -p 6379 -a wW1tUY8n cluster addslots {0..5461}
OK
# redis-cli -h 1x.xxx.8.11 -p 6379 -a wW1tUY8n cluster addslots {5462..10922}
OK
# redis-cli -h 1x.xxx.8.12 -p 6379 -a wW1tUY8n cluster addslots {10923..16383}
OK

查看集群状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# redis-cli -h 1x.xxx.8.12 -p 6380 -a xxxxxx cluster info
cluster_state:ok
cluster_slots_assigned:10923
cluster_slots_ok:10923
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:2
cluster_current_epoch:5
cluster_my_epoch:2
cluster_stats_messages_ping_sent:8493
cluster_stats_messages_pong_sent:8077
cluster_stats_messages_meet_sent:3
cluster_stats_messages_sent:16573
cluster_stats_messages_ping_received:8075
cluster_stats_messages_pong_received:8496
cluster_stats_messages_meet_received:2
cluster_stats_messages_received:16573

完成了

使用hostname部署redis7集群

配置服务器的hosts

1
2
3
echo '1x.xxx.x.x paas-m-k8s-master-1' >> /etc/hosts
echo '1x.xxx.x.x paas-m-k8s-master-2' >> /etc/hosts
echo '1x.xxx.x.x paas-m-k8s-master-3' >> /etc/hosts
1
redis-cli --cluster create paas-m-k8s-master-1:5100 paas-m-k8s-master-2:5100 paas-m-k8s-master-3:5100 --cluster-replicas 0

因为我只起了3个主节点,所有cluster-replicas设置为0

image-20230926183207463

image-20230926183415393

在cluster nodes命令返回了配置的hostname

一,基础知识

redis集群可以提供水平扩展能力,cluster模式会在各个节点间自动切分数据;会将一定的容灾能力,少部分节点故障,整个集群依旧能够运行。这里我需要在细讲一下。比如一个集群有ABC三个节点,B节点挂了,整个集群是无法工作的,因为B节点上对应的散列槽找不到了。再比如AB A‘B’这样的集群,如果B节点挂了,整个集群也是挂掉的,你可能会说不是还有B’这个备节点吗?很抱歉,因为B挂了,只剩下A一个主节点,是无法完成选举的,也就是B‘并不能自动变为B。所以集群至少要搭3主3备。

搭建cluster模式,需要redis3.0以上版本。

TCP端口要求:一个是用于客户端连接的端口(默认6379),另一个是用于集群间通信的端口(默认10000+6379)

这两个端口的偏移量10000是固定的,所以部署前先检查防火墙端口是否都已经打开。

Redis集群中有16384个散列槽,然后将这些槽分给你的集群节点(不一定非要均分,看你自己的实际情况)

集群扩容和缩容就是对应的增加和减少节点。而增加和减少节点就涉及到槽的迁移。当一个节点上的槽数量为0时,这个节点就可以下掉了。要注意的是在槽的迁移过程中,是不需要停机的。服务是正常的,但还是建议在业务不繁忙的情况下进行。

另外提一点,redis是根据key就行散列,然后确定落到哪个槽里,但要点是如果在关键字{}括号内有一个子字符串,那么只有该花括号“{}”内部的内容被散列,例如 this{foo}key 和 another{foo}key 保证在同一散列槽中

redis的一致性保证

redis并不保证很强的一致性,因为redis默认采取异步复制,在某些情况下回发生写入丢失。

比如主节点A在接受写入后便会想客户端返回确认,但是在未完成同备节点的同步时便挂了,那么这个写入就丢失了。如果你要求redis完成了刷盘或者主从同步再返回确认,那么这会导致redis性能极低。

官网还举了一个网络分区的例子,我不重复了,感兴趣看官网,https://redis.io/topics/cluster-tutorial

redis集群配置参数

配置参数在这个文件redis.conf

​       1、cluster-enabled <yes/no>:如果想在特定的Redis实例中启用Redis群集支持就设置为yes。 否则,实例通常作为独立实例启动。

       2、cluster-config-file :请注意,尽管有此选项的名称,但这不是用户可编辑的配置文件,而是Redis群集节点每次发生更改时自动保留群集配置(基本上为状态)的文件,以便能够 在启动时重新读取它。 该文件列出了群集中其他节点,它们的状态,持久变量等等。 由于某些消息的接收,通常会将此文件重写并刷新到磁盘上。

​       3、cluster-node-timeout :Redis群集节点可以不可用的最长时间,而不会将其视为失败。 如果主节点超过指定的时间不可达,它将由其从属设备进行故障切换。 此参数控制Redis群集中的其他重要事项。 值得注意的是,每个无法在指定时间内到达大多数主节点的节点将停止接受查询。

​       4、cluster-slave-validity-factor :如果设置为0,无论主设备和从设备之间的链路保持断开连接的时间长短,从设备都将尝试故障切换主设备。 如果该值为正值,则计算最大断开时间作为节点超时值乘以此选项提供的系数,如果该节点是从节点,则在主链路断开连接的时间未超过最大断开时间,它不会尝试启动故障切换。 例如,如果节点超时设置为5秒,并且有效因子设置为10,则与主设备断开连接超过50秒的从设备将不会尝试对其主设备进行故障切换。 请注意,如果没有从服务器节点能够对其进行故障转移,则任何非零值都可能导致Redis群集在主服务器出现故障后不可用。 在这种情况下,只有原始主节点重新加入集群时,集群才会返回可用。

​       5、cluster-migration-barrier :主设备将保持连接的最小从设备数量,以便另一个从设备迁移到不受任何从设备覆盖的主设备。

       6、cluster-require-full-coverage <yes / no>:默认为yes,就是说如果这个key的部分数据没有任何一个节点存储,则集群停止接受写入。 如果该选项设置为no,则即使只有部分子数据,群集仍将提供查询。

搭建步骤

1,下载

https://redis.io/

当前最新的稳定版本是4.0.11。压缩包只有1.7M。

2,规划

只有一台机器模拟搭建

规划7001 - 7006 部署6个端口

先建好7001-7006 6个目录,用来放redis配置文件。在每个目录下建好data目录用来存放数据

将安装包解压好

tar -zxvf redis-4.0.11.tar.gz

下载的包只有源码,需要make一下

(注意gcc -v 看下版本 需要4.2以上)

将其中的redis.conf copy一份到7001下

3,修改配置文件

修改点:

bind 1x.xx.46.25 :配一下ip

port 7001

daemonize yes : 后台启动

pidfile /home/rocketmq410/7001/redis_7001.pid :pidfele的路径,改成你自己的

logfile /home/rocketmq410/7001/redis.log : 可以打一下日志,默认是达到dev/null

dir /home/rocketmq410/7001/data/ : 存放数据的路径,必须是个目录

cluster-enabled yes

cluster-config-file nodes-7001.conf : redis节点的配置文件,起个名就好,这个文件是自动生成的

appendonly yes :开启追加保存

# appendfsync always :这两个是追加的模式,生成上根据你的需要来选择。有改变就保存还是每秒保存一次

appendfsync everysec :这里就用默认的了

改好一个后,每个对应的目录下复制一份

然后修改redis.conf 这里直接全局替换端口就好了,很快

如: :%s/7001/7003/g

4,安装ruby

redis管理cluster的脚本是用ruby写的,所以需要使用ruby。这个脚本就是src下的redis-trib.rb

单纯使用redis命令管理集群也可以,但是会非常麻烦和危险。

yum install ruby

现在的版本下,只要安装Ruby,Rubygems就会自动安装

所以这个只需要install ruby

5,安装redis的ruby接口

gem install redis

但是我遇到了报错:

ERROR: Error installing redis: redis requires Ruby version >= 2.2.2.

解决办法:

[rocketmq410@rocketmq4 ~]$ gpg –keyserver hkp://keys.gnupg.net –recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB

[rocketmq410@rocketmq4 ~]$ curl -sSL https://get.rvm.io | bash -s stable

[rocketmq410@rocketmq4 ~]$ find / -name rvm -print

/home/rocketmq410/.rvm/src/rvm

/home/rocketmq410/.rvm/src/rvm/bin/rvm

/home/rocketmq410/.rvm/src/rvm/lib/rvm

/home/rocketmq410/.rvm/src/rvm/scripts/rvm

/home/rocketmq410/.rvm/bin/rvm

/home/rocketmq410/.rvm/lib/rvm

/home/rocketmq410/.rvm/scripts/rvm

source /home/rocketmq410/.rvm/scripts/rvm

查看可用版本

[rocketmq410@rocketmq4 ~]$ rvm list known

# MRI Rubies

[ruby-]1.8.6[-p420]

[ruby-]1.8.7[-head] # security released on head

[ruby-]1.9.1[-p431]

[ruby-]1.9.2[-p330]

[ruby-]1.9.3[-p551]

[ruby-]2.0.0[-p648]

[ruby-]2.1[.10]

[ruby-]2.2[.10]

[ruby-]2.3[.7]

[ruby-]2.4[.4]

[ruby-]2.5[.1]

[ruby-]2.6[.0-preview2]

安装一个新版本

[rocketmq410@rocketmq4 ~]$ rvm install 2.4.1

中间会要输一次密码

[rocketmq410@rocketmq4 ~]$ rvm use 2.4.1

[rocketmq410@rocketmq4 ~]$ rvm use 2.4.1 –default

[rocketmq410@rocketmq4 ~]$ ruby -version

ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-linux]

OK了

继续

gem install redis

6,准备就绪,启动实例

[rocketmq410@rocketmq4 src]$ ./redis-server ~/7001/redis.conf

[rocketmq410@rocketmq4 src]$ ./redis-server ~/7002/redis.conf

[rocketmq410@rocketmq4 src]$ ./redis-server ~/7003/redis.conf

[rocketmq410@rocketmq4 src]$ ./redis-server ~/7004/redis.conf

[rocketmq410@rocketmq4 src]$ ./redis-server ~/7005/redis.conf

[rocketmq410@rocketmq4 src]$ ./redis-server ~/7006/redis.conf

[rocketmq410@rocketmq4 src]$ ps -ef | grep redis

rocketm+ 26002 1 0 11:26 ? 00:00:01 ./redis-server 1x.xx.46.25:7001 [cluster]

rocketm+ 26445 1 0 11:30 ? 00:00:00 ./redis-server 1x.xx.46.25:7002 [cluster]

rocketm+ 26450 1 0 11:30 ? 00:00:00 ./redis-server 1x.xx.46.25:7003 [cluster]

rocketm+ 26464 1 0 11:30 ? 00:00:00 ./redis-server 1x.xx.46.25:7004 [cluster]

rocketm+ 26469 1 0 11:30 ? 00:00:00 ./redis-server 1x.xx.46.25:7005 [cluster]

rocketm+ 26482 1 0 11:30 ? 00:00:00 ./redis-server 1x.xx.46.25:7006 [cluster]

rocketm+ 26487 5176 0 11:30 pts/1 00:00:00 grep –color=auto redis

7,配置集群

./redis-trib.rb create –replicas 1 1x.xx.46.25:7001 1x.xx.46.25:7002 1x.xx.46.25:7003 1x.xx.46.25:7004 1x.xx.46.25:7005 1x.xx.46.25:7006

–replicas 1 表示 为每个主节点配置1个备节点

执行,[WARNING] Some slaves are in the same host as their master 有个警告,因为主备在一台机器上是有问题的,生产上要分开部署。

[OK] All 16384 slots covered

这就搭建完成了

redis集群创建集群分配规则,前3个及节点为主节点,后面的为从节点

8,查看信息

-c 是以集群模式登录

[rocketmq410@rocketmq4 src]$ ./redis-cli -c -h 1x.xx.46.25 -p 7001

1x.xx.46.25:7001> CLUSTER INFO

cluster_state:ok

cluster_slots_assigned:16384

cluster_slots_ok:16384

cluster_slots_pfail:0

cluster_slots_fail:0

cluster_known_nodes:6

cluster_size:3

cluster_current_epoch:7

cluster_my_epoch:7

cluster_stats_messages_ping_sent:542

cluster_stats_messages_pong_sent:50

cluster_stats_messages_sent:592

cluster_stats_messages_ping_received:50

cluster_stats_messages_pong_received:50

cluster_stats_messages_update_received:1

cluster_stats_messages_received:101

1x.xx.46.25:7001> CLUSTER NODES

a0189fb279204ab2bee767587567dbd1445cc3d8 1x.xx.46.25:7003@17003 master - 0 1535687220000 3 connected 10923-16383

1c8af9390e14a3aa486a12df02bd2fdb9a0107c1 1x.xx.46.25:7004@17004 slave a0189fb279204ab2bee767587567dbd1445cc3d8 0 1535687220249 4 connected

67ea8a2a279e293416b7e14355cabf73238c3000 1x.xx.46.25:7005@17005 master - 0 1535687220000 7 connected 0-5460

5bd1384233a584d99fb9fdbab9a2a30c9a62ac21 1x.xx.46.25:7001@17001 myself,slave 67ea8a2a279e293416b7e14355cabf73238c3000 0 1535687221000 1 connected

66b16c3c134ff7f828e4b2fdd88536c04d884c83 1x.xx.46.25:7006@17006 slave 1b2a62758e7bd46e4be95fc8dcda12a1bd99723e 0 1535687222256 6 connected

1b2a62758e7bd46e4be95fc8dcda12a1bd99723e 1x.xx.46.25:7002@17002 master - 0 1535687222000 2 connected 5461-10922

  1. 使用helm安装

    1
    2
    3
    helm repo add kubesphere https://charts.kubesphere.io/main

    helm upgrade --install sonarqube sonarqube --repo https://charts.kubesphere.io/main -n kubesphere-devops-system --create-namespace --set service.type=NodePort

    http://1x.xxx.151.208:31884

  2. 配置SonarQube

    默认帐户 admin/admin 登录,改密码xxx,123

    创建管理员令牌

    SonarQube 配置-1

SonarQube 配置-2

1657d796c5cfd32e8ffabb9f0e2d378f16477028

  1. 创建webHook服务器

    获取 SonarQube Webhook 的地址。

    image-20220420141759179

    1
    2
    3
    4
    export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services ks-jenkins)
    export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
    echo http://$NODE_IP:$NODE_PORT/sonarqube-webhook/

http://1x.xxx.151.208:30180/sonarqube-webhook/

依次点击 AdministrationConfigurationWebhooks 创建一个 Webhook。

SonarQube Webhook-1

Webhook 页面信息

将 SonarQube 配置添加到 ks-installer

  1. 执行以下命令编辑 ks-installer

    1
    kubectl edit cc -n kubesphere-system ks-installer
  2. 搜寻至 devops。添加字段 sonarqube 并在其下方指定 externalSonarUrlexternalSonarToken

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    devops:
    enabled: true
    jenkinsJavaOpts_MaxRAM: 2g
    jenkinsJavaOpts_Xms: 512m
    jenkinsJavaOpts_Xmx: 512m
    jenkinsMemoryLim: 2Gi
    jenkinsMemoryReq: 1500Mi
    jenkinsVolumeSize: 8Gi
    sonarqube: # Add this field manually.
    externalSonarUrl: http://1x.xx.1.201:31377 # The SonarQube IP address.
    externalSonarToken: 00ee4c512fc987d3ec3251fdd7493193cdd3b91d # The SonarQube admin token created above.

    sonarqube:
    externalSonarUrl: http://1x.xxx.151.208:31884
    externalSonarToken: 1657d796c5cfd32e8ffabb9f0e2d378f16477028

  3. 完成操作后保存此文件。

步骤 5:将 SonarQube 服务器添加至 Jenkins

  1. 执行以下命令获取 Jenkins 的地址。

    1
    2
    3
    export NODE_PORT=$(kubectl get --namespace kubesphere-devops-system -o jsonpath="{.spec.ports[0].nodePort}" services ks-jenkins)
    export NODE_IP=$(kubectl get nodes --namespace kubesphere-devops-system -o jsonpath="{.items[0].status.addresses[0].address}")
    echo http://$NODE_IP:$NODE_PORT
  2. 您可以获得以下输出,获取 Jenkins 的端口号。

    1
    http://1x.xxx.151.208:30180
  3. 请使用地址 http://<Node IP>:30180 访问 Jenkins。安装 KubeSphere 时,默认情况下也会安装 Jenkins 仪表板。此外,Jenkins 还配置有 KubeSphere LDAP,这意味着您可以直接使用 KubeSphere 帐户(例如 admin/P@88w0rd)登录 Jenkins。有关配置 Jenkins 的更多信息,请参见 Jenkins 系统设置

  4. 点击左侧导航栏中的系统管理

  5. 向下翻页找到并点击系统配置

  6. 搜寻到 SonarQube servers,然后点击 Add SonarQube

  7. 输入 NameServer URL (http://<Node IP>:<NodePort>)。点击添加,选择 Jenkins,然后在弹出的对话框中用 SonarQube 管理员令牌创建凭证(如下方第二张截图所示)。创建凭证后,从 Server authentication token 旁边的下拉列表中选择该凭证。点击应用完成操作。

    sonarqube-jenkins-settings

    add-credentials

    如果点击添加按钮无效(Jenkins 已知问题),您可以前往系统管理下的 Manage Credentials 并点击 Stores scoped to Jenkins 下的 Jenkins,再点击全局凭据 (unrestricted),然后点击左侧导航栏的添加凭据,参考上方第二张截图用 SonarQube 管理员令牌添加凭证。添加凭证后,从 Server authentication token 旁边的下拉列表中选择该凭证。

步骤 6:将 sonarqubeURL 添加到 KubeSphere 控制台

您需要指定 sonarqubeURL,以便可以直接从 KubeSphere 控制台访问 SonarQube。

  1. 执行以下命令:

    1
    kubectl edit  cm -n kubesphere-system  ks-console-config
  2. 搜寻到 data.client.enableKubeConfig,在下方添加 devops 字段并指定 sonarqubeURL

    1
    2
    3
    4
    client:
    enableKubeConfig: true
    devops: # 手动添加该字段。
    sonarqubeURL: http://1x.xx.1.201:31377 # SonarQube IP 地址。
  3. 保存该文件。

步骤 7:重启服务

执行以下命令。

1
2
kubectl -n kubesphere-devops-system rollout restart deploy devops-apiserver
kubectl -n kubesphere-system rollout restart deploy ks-console

为新项目创建 SonarQube Token

您需要一个 SonarQube 令牌,以便您的流水线可以在运行时与 SonarQube 通信。

  1. 在 SonarQube 控制台上,点击 Create new project

    SonarQube 创建项目

  2. 输入项目密钥,例如 java-demo,然后点击 Set Up

    Jenkins 项目密钥

  3. 输入项目名称,例如 java-sample,然后点击 Generate

    创建令牌

    mqcloud: f97624b945c3707077053928534206b89db4bc1c

  4. 创建令牌后,点击 Continue

    令牌已创建

  5. 分别选择 JavaMaven。复制下图所示绿色框中的序列号,如果要在流水线中使用,则需要在凭证中添加此序列号。

    sonarqube-example

kubesphere装的jenkins默认密码是P@88w0rd

kubesphere配置凭证

  1. gitlab配置token

    jenkins-token:yiw-Dd3PkuWPx1vtgKP8

    devops: RRs12nv63xMTEUsejEbs

    harbor-id: paas Paas12345

    kubeconfig

  2. 去jenkins配置gitlab

    image-20220421093905398

    image-20220421094042415

image-20220421094359228

注意,id必须是第一步在gitlab中创建token时写的token名字

image-20220421094514482

测试连接成功

  1. 去gitlab配置webhook

第一次下载依赖

image-20220421170413153

第二次就不重新下载了

image-20220421170453895

OOM

image-20220822154721006

修改内存设置

1
kubectl -n kubesphere-devops-system edit deploy devops-jenkins

把内存都改大

docker: command not found

改用nerdctl

(112条消息) k8s最新版本1.24.3基于containerd的集群部署、打包和Jenkins流水线定义_Leoly003的博客-CSDN博客_k8s打包

KubeSphere DevOps 流水线如何去 Docker - KubeSphere 开发者社区

之前是

image-20220822173304923

/var/lib/containers

普通账户无法触发流水线

1
2
3
4
http://1x.xxx.4.1:30880/kapis/devops.kubesphere.io/v1alpha3/namespaces/demo222cg9/pipelines/xxx/pipelineruns?branch=master

http://1x.xxx.4.1:30880/kapis/devops.kubesphere.io/v1alpha3/devops/demo222cg9/pipelines/xxx

通过k8s的deploy部署一个java程序。并设置了资源限制内存1G

1
2
3
4
5
6
7
resources:
limits:
cpu: 500m
memory: 1000Mi
requests:
cpu: 300m
memory: 1000Mi

当我们启动java进程不指定Xms和Xmx时,打印一下java进程信息

1
2
3
4
5
6
7
sh-4.2# jinfo -flags 1
Attaching to process ID 1, please wait...
Debugger attached successfully.
Server compiler detected.
JVM version is 25.232-b09
Non-default VM flags: -XX:CICompilerCount=2 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=null -XX:InitialHeapSize=16777216 -XX:MaxHeapSize=262144000 -XX:MaxNewSize=87359488 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=5570560 -XX:OldSize=11206656 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops
Command line: -javaagent:/agent/skywalking-agent.jar -Dskywalking.agent.service_name=s02136::demo -Dskywalking.collector.backend_service=swagent.skywalking.paas-sit.xxx.net:11800 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/dumps/oom.dump

看到,默认是Xms是16777216,即16M。Xmx是262144000,即256M

可以看到计算的基础是容器的内存限制limit

之前有种说法是,容器环境,由于java获取不到容器的内存限制,只能获取到服务器的配置。

以前确实有这种情况,但是java为了更好的使用容器环境,在Java 10 引入了 +UseContainerSupport(默认情况下启用),通过这个特性,可以使得JVM在容器环境分配合理的堆内存。

后来这个特性也合入了JDK8U191版本,在JDK8U191版本之后的java8也是可以获取容器的内存限制的。

我们看看基础镜像的java版本:

1
2
3
4
sh-4.2# java -version
openjdk version "1.8.0_232"
OpenJDK Runtime Environment (build 1.8.0_232-b09)
OpenJDK 64-Bit Server VM (build 25.232-b09, mixed mode)

UseContainerSupport

-XX:+UseContainerSupport允许JVM 从主机读取cgroup限制,例如可用的CPU和RAM,并进行相应的配置。这样当容器超过内存限制时,会抛出OOM异常,而不是杀死容器。 该特性在Java 8u191 +,10及更高版本上可用。

注意,在191版本后,-XX:{Min|Max}RAMFraction 被弃用,引入了-XX:MaxRAMPercentage,其值介于0.0到100.0之间,默认值为25.0。

最佳实践

在应用的启动参数,设置 -XX:+UseContainerSupport,设置-XX:MaxRAMPercentage=75.0,这样为其他进程(debug、监控)留下足够的内存空间,又不会太浪费RAM。

Jenkins

安装

docker安装

1
2
3
4
5
6
7
8
9
10
11
docker run \
-u root \
-d \
-p 8080:8080 \
-p 50000:50000 \
-v jenkins-data:/var/jenkins_home \
-v /etc/localtime:/etc/localtime:ro \
-v /var/run/docker.sock:/var/run/docker.sock \
--name jenkins-blueocean \
--restart=always \
jenkinsci/blueocean

-v /etc/localtime:/etc/localtime:ro 作用是同步主机时区

-v /var/run/docker.sock:/var/run/docker.sock

表示Docker守护程序通过其监听的基于Unix的套接字。 该映射允许 jenkinsci/blueocean 容器与Docker守护进程通信, 如果 jenkinsci/blueocean 容器需要实例化 其他Docker容器,则该守护进程是必需的。

1
2
或者不是通过volume,也可以直接挂载到服务器的目录上,这样查看文件比较方便
-v $HOME/jenkins_home:/var/jenkins_home

初始化的密码

image-20211028103544552

手册登录需要密码。密码在/var/jenkins_home/secrets/initialAdminPassword

这个/var/jenkins_home是挂载的volume

1
2
3
4
5
6
7
8
# docker volume ls
DRIVER VOLUME NAME
local jenkins-data
# docker volume inspect jenkins-data
找到路径
# cd /var/lib/docker/volumes/jenkins-data/_data
# cat secrets/initialAdminPassword
24125b86278b4300b257b374f8f51385

安装插件并设置用户

image-20211028103644003

安装推荐的插件

image-20211028103828206

image-20211028103907058

本地构建

Jenkins是可以构建本地任务的。

只要将git仓库下载到jenkin本地的路径下。jenkins可以识别这是一个git仓库进而构建它。

注意:使用docker部署的,所以填写的路径是jenkins容器里的路径。

我之前用-v $HOME/jenkins_home:/var/jenkins_home将/var/jenkins_home目录挂载出来了。

image-20220706143552593

不用尝试了,会报错

1
Checkout of Git remote '/var/jenkins_home/GitHub/simple-java-maven-app' aborted because it references a local directory, which may be insecure. You can allow local checkouts anyway by setting the system property 'hudson.plugins.git.GitSCM.ALLOW_LOCAL_CHECKOUT' to true.

不想解决了,没什么意义

远程构建

gitlab凭证

到gitlab系统船舰一个access_token:地址是/profile/personal_access_tokens

创建一个token,注意保存好。公司的: ssjxhFrm8rkNU5yePYho

在jenkins全局模式里面配置gitlab的用户令牌验证;**jenkins >> 系统设置 >> Gitlab;在Gitlab处进行配置

img

然后新建项目 >> 源码管理 >> 添加凭据 >> 构建触发器 >> 创建webhook;

img

img

img

jenkins配置构建器

img

****上面图中的这两个东西非常重要,等下都要用到。记得保存应用!!!****

http://1x.xxx.151.216:9999/project/gitlabTest

d77fce444619dfe1e0bdeb5d93c2a330 高级-generator

gitlab配置webhook

image-20220708163330324

image-20220708165117545

把上一步的信息填过来

使用pipline远程构建

上面是使用的freestyle,一般我们使用pipline比较多

在这里插入图片描述

配置构建器和自由模式一样

只是下面流水线选上仓库地址即可

在这里插入图片描述

maven打包

创建外部挂载的settings.xml

1
2
3
4
5
6
[root@paas-m-k8s-node-6 maven]# ll
总用量 4
-rw-r--r-- 1 root ftpuser 681 10月 29 10:06 settings.xml
[root@paas-m-k8s-node-6 maven]# pwd
/var/lib/docker/volumes/jenkins-data/_data/maven

一个完整Jenkinsfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
pipeline {
agent any
environment {
// 每个阶段都会有自己的WORKSPACE,mvn打包时要指定是/var/jenkins_home/workspace/java-devops-demo,而不是/var/jenkins_home/workspace/java-devops-demo@2一个临时目录
WS = "${WORKSPACE}"
J_HOME = "${JENKINS_HOME}"
APPNAME = "demo"
VERSION = "test"
}
// 定义流水线的阶段
stages {
// 每一个阶段
stage('环境检查') {
steps {
sh 'printenv'
sh 'pwd && ls -alh'
sh 'java -version'
sh 'git --version'
sh 'docker version'
}
}
stage('代码编译') {
// 每个阶段可以使用自己的agent,这样java可以用maven的镜像。前端就用node的镜像
agent {
docker {
image 'maven:3-alpine'
// 将依赖包挂载出去,下次可用
args '-v maven-repo:/root/repository'
}
}
// 具体操作
steps {
// 发现是在/var/jenkins_home/workspace/java-devops-demo@2一个临时目录
sh 'pwd && ls -alh'
sh 'mvn -v'
// 在容器的 agent里是取不到env的,需要在前面自定义一下
sh 'echo ${JENKINS_HOME}'
// 要去workspace打包
// -s指定我们自己的settings.xml
// settings里指定本地库地址就是/root/repository,这个地址挂载出去了
sh 'cd ${WS} && mvn clean package -s "${J_HOME}/maven/settings.xml" -Dmaven.test.skip=true'
sh 'pwd && ls -alh'
}
}
stage('测试') {
steps {
sh 'pwd && ls -alh'
}
}
stage('打镜像') {
steps {
sh 'docker version'
sh 'pwd && ls -alh'
sh 'docker build -t ${APPNAME}:${VERSION} .'
}
}
stage('部署') {
steps {
echo '部署'
sh 'pwd && ls -alh'
sh 'docker run -d -p 8888:8080 --name ${APPNAME} ${APPNAME}:${VERSION}'
}
}
}
}

交互式确认

groovy脚本进行判断

并行任务

报错解决

1. Invalid agent type “docker” specified

1
2
3
4
5
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:

WorkflowScript: 3: Invalid agent type "docker" specified. Must be one of [any, label, none] @ line 3, column 9.

docker {

原因:

必须安装 2 个插件:Docker pluginDocker Pipeline

开始部署时有一些插件安装失败

2.执行sh 文件无权限问题

1
2
3
4
5
6
[root@paas-m-k8s-node-6 jenkins_home]# docker ps | grep jenkins
916dc1efbcf7 jenkinsci/blueocean "/sbin/tini -- /usr/…" 5 hours ago Up 5 hours 0.0.0.0:50000->50000/tcp, 0.0.0.0:9999->8080/tcp jenkins-blueocean

[root@paas-m-k8s-node-6 jenkins_home]# vim /var/lib/docker/containers/916dc1efbcf7781cf59ee1e97ac873a931ad1a87213a8582b6c5462cea54ea26/config.v2.json
修改$JENKINS_USER
JENKINS_USER="root"

cover_image

containerd配置镜像加速

原创 hello云胜 hello云胜 运维开发笔记


在小说阅读器中沉浸阅读

总结写在前面:

我在配置镜像加速的过程中是走了不少弯路的。下面的文章是记录了整个配置的过程,你需要看完全部文字后再操作,不要按照我写的步骤来。

正确的配置步骤是:

  • 获取镜像加速器地址
  • 配置certs.d下的配置文件
  • 配置containerd加速,修改/etc/containerd/config.toml
  • 配置nerdctl加速,修改/etc/nerdctl/nerdctl.toml

获取镜像加速器地址

之前使用阿里云的镜像加速器,现在已经不好用了,拉不到外网镜像,换成了华为云的,测试是好用的。

使用华为云的私有镜像加速器

Image

修改containerd的配置文件

containerd文件配置的修改需要根据自己的containerd版本查询官方文档

https://github.com/containerd/containerd/blob/v1.6.33/docs/cri/registry.md


vim /etc/containerd/config.toml

config.toml内容比以前docker daemon.json多很多。

在 [plugins.”io.containerd.grpc.v1.cri”.registry] 下添加 mirrors (镜像源),格式如下:


[plugins.”io.containerd.grpc.v1.cri”.registry]
  # 对docker.io进行私有镜像加速源
  [plugins.”io.containerd.grpc.v1.cri”.registry.mirrors.”docker.io”]
    endpoint = [
      “https://你自己的id.mirror.swr.myhuaweicloud.com”  # 替换为你的华为云云私有加速地址
    ]
  # 对registry.k8s.io官方镜像加速
  [plugins.”io.containerd.grpc.v1.cri”.registry.mirrors.”registry.k8s.io”]
    endpoint = [
        “https://你自己的id.mirror.swr.myhuaweicloud.com” # 替换为你的
    ]

测试crictl

现在使用crictl pull测试一下


[root@k8s-node0 ~]# crictl pull nginx:latest
Image is up to date for sha256:60adc2e137e757418d4d771822fa3b3f5d3b4ad58ef2385d200c9ee78375b6d5
[root@k8s-node0 ~]# crictl images | grep nginx
docker.io/library/nginx                                                           latest              60adc2e137e75       59.8MB

没有问题,但是测试nerdctl pull会报错


[root@k8s-node0 ~]# nerdctl pull nginx:latest
docker.io/library/nginx:latest: resolving      |————————————–|
elapsed: 29.9s                  total:   0.0 B (0.0 B/s)
INFO[0030] fetch failed                                  error=”failed to do request: Head "https://registry-1.docker.io/v2/library/nginx/manifests/latest\“: dial tcp 96.44.137.28:443: i/o timeout” host=registry-1.docker.io
ERRO[0030] active check failed                           error=”context canceled”
FATA[0030] failed to resolve reference “docker.io/library/nginx:latest”: failed to do request: Head “https://registry-1.docker.io/v2/library/nginx/manifests/latest“: dial tcp 96.44.137.28:443: i/o timeout

拉取失败,并没有使用加速镜像

配置nerdctl

网上很多说的都不对。

查看nerdctl的官方说明,发现这么一条

Image

那就是nerdctl会忽略[plugins.”io.containerd.grpc.v1.cri”.registry]配置,所以上面的配置对containerd生效,但是对nerdctl不生效

对nerdctl应该这么配置

nerdctl.toml

nerdctl使用自己的nerdctl.toml配置文件。(我是root模式)


vim /etc/nerdctl/nerdctl.toml


# This is an example of /etc/nerdctl/nerdctl.toml .
# Unrelated to the daemon’s /etc/containerd/config.toml .

address        = "unix:///run/containerd/containerd.sock"  
namespace      = "k8s.io"  
snapshotter    = "overlayfs"  
cgroup_manager = "systemd"  
hosts_dir      = ["/etc/containerd/certs.d"]  
insecure_registry = true

创建certs.d目录,然后根据你要加速的域名创建对应的目录


mkdir -p /etc/containerd/certs.d
mkdir -p /etc/containerd/certs.d/docker.io
mkdir -p /etc/containerd/certs.d/registry.k8s.io

域名目录下创建hosts.toml文件,内容如下


server = “https://docker.io

[host."https://你自己的id.mirror.swr.myhuaweicloud.com"]  
  capabilities = ["pull", "resolve"]  

registry.k8s.io下创建hosts.toml文件,内容如下


server = “https://registry.k8s.io

[host."https://你自己的id.mirror.swr.myhuaweicloud.com"]  
  capabilities = ["pull", "resolve"]

再次测试


[root@k8s-node0 certs.d]# crictl rmi docker.io/library/nginx:latest
Deleted: docker.io/library/nginx:latest
[root@k8s-node0 certs.d]# nerdctl pull nginx:latest
WARN[0000] skipping verifying HTTPS certs for “docker.io”
docker.io/library/nginx:latest:                                                   resolved       |++++++++++++++++++++++++++++++++++++++|
docker.io/library/nginx:latest:                                                   resolved       |++++++++++++++++++++++++++++++++++++++|
index-sha256:553f64aecdc31b5bf944521731cd70e35da4faed96b2b7548a3d8e2598c52a42:    done           |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:5c733364e9a8f7e6d7289ceaad623c6600479fe95c3ab5534f07bfd7416d9541: done           |++++++++++++++++++++++++++++++++++++++|
config-sha256:60adc2e137e757418d4d771822fa3b3f5d3b4ad58ef2385d200c9ee78375b6d5:   done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:de57a609c9d5148f10b38f5c920d276e9e38b2856fe16c0aae1450613dc12051:    done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:0e4bc2bd6656e6e004e3c749af70e5650bac2258243eb0949dea51cb8b7863db:    done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:b5feb73171bf1bcf29fdd1ba642c3d30cdf4c6329b19d89be14d209d778c89ba:    done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:108ab82928207dabd9abfddbc960dd842364037563fc560b8f6304e4a91454fe:    done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:53d743880af45adf9f141eec1fe3a413087e528075a5d8884d6215ddfdd2b806:    done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:77fa2eb0631772679b0e48eca04f4906fba5fe94377e01618873a4a1171107ce:    done           |++++++++++++++++++++++++++++++++++++++|
layer-sha256:192e2451f8751fb74549c932e26a9bcfd7b669fe2f5bd8381ea5ac65f09b256b:    done           |++++++++++++++++++++++++++++++++++++++|
elapsed: 19.1s                                                                    total:  57.0 M (3.0 MiB/s)

可以了。

再回头改下/etc/containerd/config.toml

这样我们对containerd和nerdctl使用了两处不同的配置。

这样不好,其实可以将containerd的加速镜像也配置到/etc/containerd/certs.d。

修改如下,把之前配置的[plugins.”io.containerd.grpc.v1.cri”.registry]下的内容都删除即可。


[plugins.”io.containerd.grpc.v1.cri”.registry]
      config_path = “/etc/containerd/certs.d”

重启下containerd


systemctl restart containerd

作者:陈维贤
链接:https://zhuanlan.zhihu.com/p/146958975
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

01竞业协议到底是啥?

进大厂难,出大厂更难,想在大厂之间 “反复横跳” 更是难上加难!
脉脉上就有不少大厂员工爆料,称受竞业协议限制,离职后几乎不能到任何知名企业工作。 所以,这个坑爹的竞业协议究竟是什么鬼?进大厂非得签这个竞业协议么?

1)竞业协议到底是啥?

所谓竞业协议,又称 “竞业禁止协议”,指公司为了保护自己的商业利益,禁止员工在离职后前往竞品公司就职的一项制度。 说人话就是 —— 离职后不许到「原公司规定的对家」工作。 当然,老东家每个月还会给你点补偿金,不太多,基本就原薪资的 30%,只保证你不被饿死。 但是,你如果拿了老东家的钱,还要跳槽到对家去,那老东家就有权把你告上法庭,让你 N 倍赔偿补偿金。

img

前百度员工因违反竞业协议被判赔偿83万 和普通协议不同,竞业协议并不是签了就立马生效的,而是分「签署」和「启动」两个阶段。

① 签署

虽然说,签署竞业协议**号称是“自愿”**的,但是,员工真的有选择的权利吗? 很多公司会在涉及到你关键利益的节点,让你签竞业协议。比如入职前、获得公司期权前,甚至是开离职证明前…… 如果不签,利益受损是很难避免的。 有的网易员工就在脉脉上爆料,必须签一份很苛刻的竞业协议,才能拿股票期权:

img

② 启动

虽然是自己“自愿”签的,但是离职后,是否启动这份竞业协议,就由不得员工了——主动权掌握在公司手里。 只要公司选择启动协议并开始发放补偿金,不管你同不同意,都视为协议生效。 腾讯员工就表示自己离职时被启动竞业,措手不及:

img

之前还有某厂员工,在竞业协议的落款处写了大大的“不”字,但是还是被强行启动了竞业协议,最后被法院判了违反竞业协议,要赔公司天文数字…… 其实,这条法例本来是国家为了防止公司之间的恶性竞争制定的。
一般来说,只有涉及到公司核心商业机密的职位,才会签署这项竞业协议。 但是,为了做好 “人才截留” ,让对家也得不到自己流失的人才,很多大厂已经迈出了全员签署竞业协议的步伐,连实习生也不放过:

img

这……这简直就是得不到就要毁掉的最佳诠释吧。

2)竞业调查有多狠?

互联网大厂们针开展竞业调查的手段有多狠,我们根本想象不到: 比如,前公司会给竞品公司邮寄空快递,如果员工签收了,就算坐实了违反竞业协议,马上安排告上法庭:

img

刚跳槽就不要随便 “剁手” 了 你以为钓鱼包裹是大厂 “追杀” 前员工的最狠的手段吗? no no no ,必要时候他们还会派出私家侦探盯住你…… 关于竞业,有一个很出名的案例: 字节跳动曾经派出过私家侦探,蹲守某跳槽腾讯的应届生员工,还把他刷卡进出大楼的照片作为起诉他的证据之一:

img

除此之外,签收记录、电话录音等,一切可以证明你在竞品公司工作的资料,都可以被当作证据,提交给法庭。 据《财经》调查,互联网大厂进行竞业禁止调查的手段,主要有以下5种:

寄快递或假装快递员,向竞品公司给前员工寄送包裹,在前员工签收时录下全程视频;

调取前员工的社保记录

询问竞品公司的前台等员工,或直接打匿名电话向本人证实。“请问你是/这里有xxx (title) 吗?”,如果得到确定回答,这份录音会成为呈堂证供;

私家侦探跟拍;

媒体报道、朋友圈、甚至是微信聊天记录等一切相关消息渠道。

看到这里,你可能会产生疑问,这些通过「非常规手段」取得的证据,真的具有法律效用么? 查了多个庭审案例后,我发现,其实最后起决定性作用的还是一些严肃证据,比如 “社保记录”、“个税代缴记录” 等。

img

所以说,像私家侦探、录音视频这种辅助手段,可以作为证据提交,但作用不大。
这些证据,主要还是为了攻破离职员工的心理防线,迫使员工主动从竞品公司离职。

02**丢工作、少赚钱,**竞业协议有多坑?

可能有人会问,竞业协议听着挺好的,还给补偿金,上一份班拿两份钱,它不香吗? 当然不香! 对大部分职场人来说,“被竞业”简直就是大难临头,你的会被迫“中断”职业生涯、钱不够花,甚至是被骚扰……

① 钱不够花

别看人家调查竞业的时候不惜一切人力物力代价,对于真正乖乖遵守协议的人,他们倒是开始“一毛不拔”。 首先,竞业协议规定,发放的补偿金不得低于原工资的 30% 。话虽如此,很多公司都把这条协议默认为**“只支付 30%”。** 在一线城市,这点钱还不够还房贷的呢…… 比如某网易员工,被原领导穿小鞋挤走了不说,还被骗签了一个十分苛刻的竞业协议,拿到的补偿金连房贷还不上,只能发文怒斥“网易给我上了人生中最重要的一课”:

img

这位兄弟的遭遇有多惨我不多赘述了,看这惊人的“在看”数,也能感受到大家对他有多同情…… 其次,很多岗位的工资,都是以“低底薪+高提成”的模式支付的,比如 BD 、销售。一旦遭遇竞业,原公司只需要支付底薪的 30% 就可以了。 举个例子,某些平台的 BD 岗位,底薪 5000 、提成 7000 ,一旦被竞业,每个月就只能拿到 1500 的竞业补偿……就这么点钱就能把你圈住,公司何乐而不为呢? 另外,还有一些公司会“无意”把员工的税算错,也是为了减少竞业补偿的发放。 最后,我国法律规定,企业连续 3 个月不支付补偿金,才算是竞业协议失效。因此,很多公司选择在竞业协议还有 3 个月到期时,直接停止支付补偿金。 竞业协议依然生效,还不用给钱……这一招空手套白狼,真是绝妙。

② 职业生涯中断

现在的互联网大厂的业务涉及都很广,因此厂之间大多有业务重叠。 也就是说,离开了一家大厂后,可能你就很难再在其他大厂入职了,比如百度的竞业对象:

img

请问员工离开百度是要直接饿死公司才满意吗
一般来说,非核心人员的竞业协议有效期是一年,核心人员、高管等有效期会长达两年。 在瞬息万变的互联网时代,两年足以让很多事情做出翻天覆地的改变了。 很多背着竞业协议的人才,为了养家糊口,不得不去降薪去一些很不起眼的小公司就职。 两年时间过去,不仅身价降了,视野也窄了不少,整个职业生涯都会受到影响。

③ 被骚扰

前不久,一条脉脉职言的帖子在网上流传,称自己怀孕离职后持续遭到字节跳动的骚扰,不仅少算竞业补偿、寄钓鱼包裹,联系包裹发件人还要遭到辱骂……

img

另外一位实名 diss 今日头条的勇士,也有一份“被竞业”的惨痛经历:

离职时拒签竞业,直接被今日头条起诉,要求赔公司 150w ;

仲裁驳回了还不罢休,继续向法院上诉。

img

不过,这两条帖子目前已经看不到了,不知是被公关了,还是因为真实性存疑。 虽说竞业如此严格,但万事总有例外。 前几天,前魅族高管杨柘刚刚因为“想照顾家庭”离职,就火速出任小米中国区 CMO ,仿佛竞业协议是一场梦,醒了只剩很感动:

img

小米新任 CMO 杨柘,曾就职过三星、华为、魅族等著名手机厂商 这就很迷,杨柘不是要多照顾家庭吗,为啥还去小米上班?还光明正大的发微博显摆? 这么快乐,雷总是不是给他在公司旁边买房、发媳妇了……

img

难道说,真正的大佬们,都不 care 竞业协议? 当然不是! 管理者们接触的核心机密更多,当然也背负着更严苛的竞业协议。
对于大佬来说,我们这些普通人最怕的赔钱加从竞品公司辞职走人,都是竞业调查“最好的”结果。 一招不慎,你可能身败名裂,甚至锒铛入狱…… 比如,今年年初,前联想副总裁常程宣布跳槽小米,负责小米手机产品线。 在此之前,常程已在联想工作近二十年,联想表示保留起诉权利:

img

当然,联想还是比较仁慈,只是预备起诉;腾讯就比较狠了,贡献了国内最早、最轰动的案例: 2013 年,时任腾讯电子商务部总经理的刘春宁,宣布自己要离职创业后,转身却拿着腾讯的股票加入了阿里巴巴,当月就被任命为阿里数字事业群总裁。 刘春宁出走 2 年后,遭到腾讯的“内部举报、审计”,称其“在职期间有贪腐问题”,被深圳警方带走。
不仅阿里总裁做不成,还直接成了阶下囚

img

要说腾讯还是 6 ,你走再久,我也能想办法把你拉下水。 还有以“狼性”著称的华为,先是把 6 个中高层以“泄密”为由全抓了。 酷派 CEO 当时还直接跳出来背锅,表示这些人中有入职酷派的,就差把“我能抢过华为”写脸上了:

img

03结语

如果你要问,“竞业协议” 真有这么重要吗?当然! 随着**互联网巨头业务的互相交错,人才竞争也越来越激烈。**因此,各个巨头之间的抢人大战,说是“腥风血雨”也不为过。 董明珠曾经公开吐槽过奥克斯“天天挖人”,还帮助跳槽员工制造新身份,躲避格力的竞业调查:

img

百度更惨,北京互联网中层以上,一半都是百度人:

img

话虽如此,但是“全员竞业”的确没有必要。 不得不承认,现在很多互联网大厂都把竞业协议当做打压对家的手段。
不仅公司为此付出了高额的金钱代价,许多无辜的员工也被迫“陪跑”,损失更是无法估量。 时代的一粒灰,落到个人身上就是一座山。**
**没有一个个体,应当为公司之间的商业竞争买单。

小米笔记本加装固态硬盘

忽然发现,我这个小米笔记本13.3版本的也跟了我快5年了,依然很坚挺,质量不错。

只是原始的配置磁盘只有250G的ssd。空间捉急。

一直外接移动硬盘使用。现在想再装个ubuntu双系统。已经没有空间了。就想能不能扩个硬盘。

查了下,这款笔记本正好留了一个扩展槽。

扩展槽接口是M.2 2280,协议是SATA。所以购买ssd的时候要注意

加装硬盘

材料准备

微信图片_20221217162818

之前买的修手机的工具正好派上用场了。

一共8颗螺丝,长度不一样,注意一下。

微信图片_20221217162810

有一颗螺丝要掰开这个小脚

微信图片_20221217162802

比较紧,用吸盘吸开。

微信图片_20221217162755

这个就是ssk扩展槽

微信图片_20221217162747

把硬盘插上,让卖家送了螺丝,固定好。

就是这么简单,但是还没完,还需要开机再设置下磁盘。

磁盘管理

Snipaste_2022-12-17_16-06-26

开始-右键打开磁盘管理。点击确定。

Snipaste_2022-12-17_16-13-22

看到未分配的磁盘。右键,新建简单卷。

Snipaste_2022-12-17_16-13-55

一路默认确定即可

Snipaste_2022-12-17_16-14-58

ok,搞定